Skip to content

Commit 21db307

Browse files
authored
Merge pull request #93 from ThePrez/fix/tersedata
Handle terse data format from server for SQL results
2 parents 6fc6aaf + 68f4202 commit 21db307

File tree

6 files changed

+54
-13
lines changed

6 files changed

+54
-13
lines changed

src/connection/manager.ts

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,16 @@ export class SQLJobManager {
9090
return (this.selectedJob >= 0);
9191
}
9292

93-
async runSQL<T>(query: string, opts: QueryOptions = {}): Promise<T[]> {
93+
/**
94+
* Runs SQL
95+
* @param query the SQL query
96+
* @param parameters the list of parameters (indicated by '?' parameter parkers in the SQL query)
97+
* @param isTerseResults whether the returned data is in terse format. When set to true, the data is returned as an array
98+
* of arrays. When set to false, data is returned as an array of objects (compatible with legacy API).
99+
* @returns
100+
*/
101+
async runSQL<T>(query: string, opts?: QueryOptions): Promise<T[]> {
102+
94103
// 2147483647 is NOT arbitrary. On the server side, this is processed as a Java
95104
// int. This is the largest number available without overflow (Integer.MAX_VALUE)
96105
const rowsToFetch = 2147483647;

src/connection/query.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ export class Query<T> {
1616
private rowsToFetch: number = 100;
1717
private isCLCommand: boolean;
1818
private state: QueryState = QueryState.NOT_YET_RUN;
19+
private isTerseResults: boolean;
1920

2021
public shouldAutoClose: boolean;
2122

@@ -26,6 +27,7 @@ export class Query<T> {
2627
this.sql = query;
2728
this.isCLCommand = opts.isClCommand;
2829
this.shouldAutoClose = opts.autoClose;
30+
this.isTerseResults = opts.isTerseResults;
2931

3032
Query.globalQueryList.push(this);
3133
}
@@ -70,13 +72,15 @@ export class Query<T> {
7072
queryObject = {
7173
id: SQLJob.getNewUniqueId(`clcommand`),
7274
type: `cl`,
75+
terse: this.isTerseResults,
7376
cmd: this.sql
7477
};
7578
} else {
7679
queryObject = {
7780
id: SQLJob.getNewUniqueId(`query`),
7881
type: this.isPrepared ? `prepare_sql_execute` : `sql`,
7982
sql: this.sql,
83+
terse: this.isTerseResults,
8084
rows: rowsToFetch,
8185
parameters: this.parameters
8286
};

src/connection/types.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ export enum ServerTraceDest {
2929
IN_MEM = "IN_MEM"
3030
}
3131
export interface QueryOptions {
32+
isTerseResults?: boolean;
3233
isClCommand?: boolean,
3334
parameters?: any[],
3435
autoClose?: boolean

src/testing/jobs.ts

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -99,7 +99,38 @@ export const JobsSuite: TestSuite = {
9999

100100
newJob.close();
101101
}},
102+
{name: `Query with non-terse results`, test: async () => {
103+
assert.strictEqual(ServerComponent.isInstalled(), true);
104+
105+
let newJob = new SQLJob({libraries: [`QIWS`], naming: `system`});
106+
await newJob.connect();
102107

108+
let rowsAtATime = 4;
109+
let qry = newJob.query(`select * from QIWS.QCUSTCDT limit 1`,{isTerseResults: false});
110+
let qryResults = await qry.run(rowsAtATime);
111+
112+
assert.equal(qryResults.success, true);
113+
let firstRow = qryResults.data[0];
114+
let cusnum = firstRow[`CUSNUM`];
115+
assert.equal(cusnum === undefined, false);
116+
assert.equal(Array.isArray(firstRow), false);
117+
newJob.close();
118+
}},
119+
{name: `Query with terse results`, test: async () => {
120+
assert.strictEqual(ServerComponent.isInstalled(), true);
121+
122+
let newJob = new SQLJob({libraries: [`QIWS`], naming: `system`});
123+
await newJob.connect();
124+
125+
let rowsAtATime = 4;
126+
let qry = newJob.query(`select * from QIWS.QCUSTCDT limit 1`,{isTerseResults: true});
127+
let qryResults = await qry.run(rowsAtATime);
128+
129+
assert.equal(qryResults.success, true);
130+
let firstRow = qryResults.data[0];
131+
assert.equal(Array.isArray(firstRow), true);
132+
newJob.close();
133+
}},
103134
{name: `Can round-trip Extended characters`, test: async () => {
104135
assert.strictEqual(ServerComponent.isInstalled(), true);
105136

src/views/results/html.ts

Lines changed: 6 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,6 @@ export function generateScroller(basicSelect: string, isCL: boolean): string {
5454
let totalRows = 0;
5555
let noMoreRows = false;
5656
let isFetching = false;
57-
let columnList = [];
5857
5958
window.addEventListener("load", main);
6059
function main() {
@@ -82,17 +81,14 @@ export function generateScroller(basicSelect: string, isCL: boolean): string {
8281
isFetching = false;
8382
noMoreRows = data.isDone;
8483
85-
if (mustLoadHeaders) {
86-
columnList = event.data.columnList;
87-
88-
setHeaders('resultset', columnList);
89-
84+
if (mustLoadHeaders && event.data.columnList) {
85+
setHeaders('resultset', event.data.columnList);
9086
mustLoadHeaders = false;
9187
}
9288
9389
if (data.rows && data.rows.length > 0) {
9490
totalRows += data.rows.length;
95-
appendRows('resultset', columnList, data.rows);
91+
appendRows('resultset', data.rows);
9692
}
9793
9894
const nextButton = document.getElementById("nextButton");
@@ -141,19 +137,19 @@ export function generateScroller(basicSelect: string, isCL: boolean): string {
141137
});
142138
}
143139
144-
function appendRows(tableId, colList, arrayOfObjects) {
140+
function appendRows(tableId, arrayOfObjects) {
145141
var tBodyRef = document.getElementById(tableId).getElementsByTagName('tbody')[0];
146142
147143
for (const row of arrayOfObjects) {
148144
// Insert a row at the end of table
149145
var newRow = tBodyRef.insertRow();
150146
151-
for (const columnName of colList) {
147+
for (const cell of row) {
152148
// Insert a cell at the end of the row
153149
var newCell = newRow.insertCell();
154150
155151
// Append a text node to the cell
156-
var newText = document.createTextNode(row[columnName] === undefined ? 'null' : row[columnName]);
152+
var newText = document.createTextNode(cell === undefined ? 'null' : cell);
157153
newCell.appendChild(newText);
158154
}
159155
}

src/views/results/index.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ class ResultSetPanelProvider {
4141
// We will need to revisit this if we ever allow multiple result tabs like ACS does
4242
Query.cleanup();
4343

44-
let query = await JobManager.getPagingStatement(message.query, { isClCommand: message.isCL, autoClose: true });
44+
let query = await JobManager.getPagingStatement(message.query, { isClCommand: message.isCL, autoClose: true, isTerseResults: true });
4545
queryObject = query;
4646
}
4747

@@ -161,7 +161,7 @@ export function initialise(context: vscode.ExtensionContext) {
161161

162162
} else {
163163
// Otherwise... it's a bit complicated.
164-
const data = await JobManager.runSQL(statement.content);
164+
const data = await JobManager.runSQL(statement.content, undefined, true);
165165

166166
if (data.length > 0) {
167167
switch (statement.type) {

0 commit comments

Comments
 (0)