From 30fde5abfdd3e2b5928b5ef8ccb871ad7ee7ff78 Mon Sep 17 00:00:00 2001 From: ajshedivy Date: Tue, 3 Oct 2023 16:31:21 -0500 Subject: [PATCH 01/12] add initial work for self codes --- package.json | 15 +++++++++ src/views/jobManager/jobManagerView.ts | 31 +++++++++++++++++++ src/views/jobManager/selfCodes/selfCodes.ts | 25 +++++++++++++++ .../jobManager/selfCodes/selfCodesBrowser.ts | 17 ++++++++++ src/views/jobManager/statusBar.ts | 1 + 5 files changed, 89 insertions(+) create mode 100644 src/views/jobManager/selfCodes/selfCodes.ts create mode 100644 src/views/jobManager/selfCodes/selfCodesBrowser.ts diff --git a/package.json b/package.json index 19ed110e..618072ce 100644 --- a/package.json +++ b/package.json @@ -289,6 +289,12 @@ "category": "Db2 for i", "icon": "$(edit)" }, + { + "command": "vscode-db2i.jobManager.editSelfCodes", + "title": "Edit SELFCODES", + "category": "Db2 for i", + "icon": "$(bracket-error)" + }, { "command": "vscode-db2i.jobManager.copyJobId", "title": "Copy Job Name", @@ -348,6 +354,10 @@ "command": "vscode-db2i.jobManager.editJobProps", "when": "never" }, + { + "command": "vscode-db2i.jobManager.editSelfCodes", + "when": "never" + }, { "command": "vscode-db2i.jobManager.copyJobId", "when": "never" @@ -519,6 +529,11 @@ "when": "view == jobManager && viewItem == sqlJob", "group": "inline" }, + { + "command": "vscode-db2i.jobManager.editSelfCodes", + "when": "view == jobManager && viewItem == sqlJob", + "group": "inline" + }, { "command": "vscode-db2i.jobManager.copyJobId", "when": "view == jobManager && viewItem == sqlJob", diff --git a/src/views/jobManager/jobManagerView.ts b/src/views/jobManager/jobManagerView.ts index edc8d68f..ec9be995 100644 --- a/src/views/jobManager/jobManagerView.ts +++ b/src/views/jobManager/jobManagerView.ts @@ -9,6 +9,8 @@ import { ServerComponent } from "../../connection/serverComponent"; import { updateStatusBar } from "./statusBar"; import { SQLJob, TransactionEndType } from "../../connection/sqlJob"; import { ConfigGroup, ConfigManager } from "./ConfigManager"; +import { selfCodesMap } from "./selfCodes/selfCodes"; +import { SelfCodesQuickPickItem } from "./selfCodes/selfCodesBrowser"; const selectJobCommand = `vscode-db2i.jobManager.selectJob`; const activeColor = new vscode.ThemeColor(`minimapGutter.addedBackground`); @@ -127,6 +129,35 @@ export class JobManagerView implements TreeDataProvider { } }), + vscode.commands.registerCommand(`vscode-db2i.jobManager.editSelfCodes`, async (node?: SQLJobItem) => { + const id = node ? node.label as string : undefined; + let selected = id ? JobManager.getJob(id) : JobManager.getSelection(); + if (selected) { + try { + const selfCodeItems = selfCodesMap.map(code => new SelfCodesQuickPickItem(code)); + + const quickPick = vscode.window.createQuickPick(); + quickPick.title = `Select SELFCODES`; + quickPick.canSelectMany = true; + quickPick.matchOnDetail = true; + quickPick.items = [ + {kind: vscode.QuickPickItemKind.Separator, label: "Ryan's Favorites"}, + ...selfCodeItems, + {kind: vscode.QuickPickItemKind.Separator, label: "All Available SELFCODES"} + ]; + + quickPick.onDidAccept(() => { + const selections = quickPick.selectedItems; + quickPick.hide() + }) + quickPick.onDidHide(() => quickPick.dispose()); + quickPick.show(); + } catch (e) { + vscode.window.showErrorMessage(e.message); + } + } + }), + vscode.commands.registerCommand(`vscode-db2i.jobManager.enableTracing`, async (node?: SQLJobItem) => { if (node) { const id = node.label as string; diff --git a/src/views/jobManager/selfCodes/selfCodes.ts b/src/views/jobManager/selfCodes/selfCodes.ts new file mode 100644 index 00000000..49ce90d1 --- /dev/null +++ b/src/views/jobManager/selfCodes/selfCodes.ts @@ -0,0 +1,25 @@ +export interface SelfCodeObject { + code: string; + message: string; +} + +export const selfCodesMap: SelfCodeObject[] = [ + { code: "138", message: "Argument of substringing function not valid" }, + { code: "180", message: "Syntax of date, time, or timestamp not valid" }, + { + code: "181", + message: "Value in date, time, or timestamp string not valid", + }, + { code: "182", message: "A date, time, or timestamp expression not valid" }, + { code: "183", message: "Result of date or timestamp expression not valid" }, + { code: "199", message: "Keyword not expected, valid tokens:" }, + { code: "203", message: "Name is ambiguous" }, + { code: "204", message: "&1 in &2 type *&3 not found." }, + { code: "205", message: "Column not in table" }, + { code: "206", message: "Column or global variable not found" }, + { code: "304", message: "Conversion error in assignment to variable" }, + { code: "420", message: "Value for cast argument not valid" }, + { code: "551", message: "Not authorized to object &1 in &2 type *&3." }, + { code: "802", message: "Data conversion or mapping error" }, + { code: "811", message: "Result of SELECT more than one row." }, +]; diff --git a/src/views/jobManager/selfCodes/selfCodesBrowser.ts b/src/views/jobManager/selfCodes/selfCodesBrowser.ts new file mode 100644 index 00000000..d96a02c9 --- /dev/null +++ b/src/views/jobManager/selfCodes/selfCodesBrowser.ts @@ -0,0 +1,17 @@ +import * as vscode from 'vscode'; +import { SelfCodeObject } from './selfCodes'; + +export class SelfCodesQuickPickItem implements vscode.QuickPickItem { + label: string; + description?: string; + detail?: string; + + constructor(object: SelfCodeObject) { + this.label = object.code; + this.description = object.message; + } +} + +export class SelfCodes { + +} \ No newline at end of file diff --git a/src/views/jobManager/statusBar.ts b/src/views/jobManager/statusBar.ts index 23a274cd..9cf0516e 100644 --- a/src/views/jobManager/statusBar.ts +++ b/src/views/jobManager/statusBar.ts @@ -33,6 +33,7 @@ export async function updateStatusBar() { toolTipItems.push(`[$(info) View Job Log](command:vscode-db2i.jobManager.viewJobLog)`); toolTipItems.push(`[$(edit) Edit Connection Settings](command:vscode-db2i.jobManager.editJobProps)`); + toolTipItems.push(`[$(bracket-error) Edit SELFCODES](command:vscode-db2i.jobManager.editSelfCodes)`); } else { text = `$(database) No job active`; toolTipItems.push(`[Start Job](command:vscode-db2i.jobManager.newJob)`); From e014ac38007e32cfa262eb6a1f2410d8c01b9e52 Mon Sep 17 00:00:00 2001 From: ajshedivy Date: Fri, 13 Oct 2023 15:06:57 -0500 Subject: [PATCH 02/12] put SQL logic in function --- src/connection/types.ts | 2 + src/views/jobManager/jobManagerView.ts | 46 +++++++++++++++---- .../jobManager/selfCodes/selfCodesBrowser.ts | 12 ++++- 3 files changed, 48 insertions(+), 12 deletions(-) diff --git a/src/connection/types.ts b/src/connection/types.ts index 0fb63c51..4d56358a 100644 --- a/src/connection/types.ts +++ b/src/connection/types.ts @@ -77,6 +77,8 @@ export interface ColumnMetaData { export type Rows = {[column: string]: string|number|boolean}[]; export interface JDBCOptions { + // selfcodes + selfcodes?: string[]; // Format properties "naming"?: "sql" | "system"; "date format"?: diff --git a/src/views/jobManager/jobManagerView.ts b/src/views/jobManager/jobManagerView.ts index ec9be995..130bc976 100644 --- a/src/views/jobManager/jobManagerView.ts +++ b/src/views/jobManager/jobManagerView.ts @@ -10,7 +10,7 @@ import { updateStatusBar } from "./statusBar"; import { SQLJob, TransactionEndType } from "../../connection/sqlJob"; import { ConfigGroup, ConfigManager } from "./ConfigManager"; import { selfCodesMap } from "./selfCodes/selfCodes"; -import { SelfCodesQuickPickItem } from "./selfCodes/selfCodesBrowser"; +import { SelfCodesQuickPickItem, setSelfCodes } from "./selfCodes/selfCodesBrowser"; const selectJobCommand = `vscode-db2i.jobManager.selectJob`; const activeColor = new vscode.ThemeColor(`minimapGutter.addedBackground`); @@ -134,22 +134,48 @@ export class JobManagerView implements TreeDataProvider { let selected = id ? JobManager.getJob(id) : JobManager.getSelection(); if (selected) { try { - const selfCodeItems = selfCodesMap.map(code => new SelfCodesQuickPickItem(code)); - + const currentSelfCodes = selected.job.options.selfcodes; + const selfCodeItems: SelfCodesQuickPickItem[] = selfCodesMap.map( + (code) => new SelfCodesQuickPickItem(code) + ); + const currentSelfCodeItems: SelfCodesQuickPickItem[] = + selfCodeItems.filter((item) => + currentSelfCodes ? currentSelfCodes.includes(item.label) : false + ); + const quickPick = vscode.window.createQuickPick(); quickPick.title = `Select SELFCODES`; quickPick.canSelectMany = true; quickPick.matchOnDetail = true; quickPick.items = [ - {kind: vscode.QuickPickItemKind.Separator, label: "Ryan's Favorites"}, - ...selfCodeItems, - {kind: vscode.QuickPickItemKind.Separator, label: "All Available SELFCODES"} + { + kind: vscode.QuickPickItemKind.Separator, + label: "Currently selected schemas", + }, + ...currentSelfCodeItems, + { + kind: vscode.QuickPickItemKind.Separator, + label: "All Available SELFCODES", + }, + ...selfCodeItems.filter((item) => + currentSelfCodeItems + ? !currentSelfCodeItems.includes(item) + : true + ), ]; - - quickPick.onDidAccept(() => { + + quickPick.selectedItems = currentSelfCodeItems; + + quickPick.onDidAccept(async () => { const selections = quickPick.selectedItems; - quickPick.hide() - }) + // SET SYSIBMADM.SELFCODES = SYSIBMADM.VALIDATE_SELF('-514, -204, -501, +30, -199'); + if (selections) { + const codes: string[] = selections.map((code) => code.label); + setSelfCodes(codes); + selected.job.options.selfcodes = codes; + } + quickPick.hide(); + }); quickPick.onDidHide(() => quickPick.dispose()); quickPick.show(); } catch (e) { diff --git a/src/views/jobManager/selfCodes/selfCodesBrowser.ts b/src/views/jobManager/selfCodes/selfCodesBrowser.ts index d96a02c9..559f57b5 100644 --- a/src/views/jobManager/selfCodes/selfCodesBrowser.ts +++ b/src/views/jobManager/selfCodes/selfCodesBrowser.ts @@ -1,5 +1,7 @@ import * as vscode from 'vscode'; import { SelfCodeObject } from './selfCodes'; +import { JDBCOptions } from '../../../connection/types'; +import { JobManager } from '../../../config'; export class SelfCodesQuickPickItem implements vscode.QuickPickItem { label: string; @@ -12,6 +14,12 @@ export class SelfCodesQuickPickItem implements vscode.QuickPickItem { } } -export class SelfCodes { - +export async function setSelfCodes(codes: string[]) { + try { + await JobManager.runSQL(`SET SYSIBMADM.SELFCODES = SYSIBMADM.VALIDATE_SELF('${codes.join(', ')}')`); + + vscode.window.showInformationMessage(`Applied SELFCODES: ${codes}`); + } catch (e) { + vscode.window.showErrorMessage(e.message); + } } \ No newline at end of file From 40fa09257ec6a5f9baac82dab0679849d82faaf3 Mon Sep 17 00:00:00 2001 From: ajshedivy Date: Mon, 16 Oct 2023 13:34:53 -0500 Subject: [PATCH 03/12] clean up typo --- src/views/jobManager/jobManagerView.ts | 2 +- src/views/jobManager/selfCodes/selfCodesBrowser.ts | 3 +-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/src/views/jobManager/jobManagerView.ts b/src/views/jobManager/jobManagerView.ts index 130bc976..74b190dc 100644 --- a/src/views/jobManager/jobManagerView.ts +++ b/src/views/jobManager/jobManagerView.ts @@ -150,7 +150,7 @@ export class JobManagerView implements TreeDataProvider { quickPick.items = [ { kind: vscode.QuickPickItemKind.Separator, - label: "Currently selected schemas", + label: "Currently selected SELFCODES", }, ...currentSelfCodeItems, { diff --git a/src/views/jobManager/selfCodes/selfCodesBrowser.ts b/src/views/jobManager/selfCodes/selfCodesBrowser.ts index 559f57b5..5053e0ef 100644 --- a/src/views/jobManager/selfCodes/selfCodesBrowser.ts +++ b/src/views/jobManager/selfCodes/selfCodesBrowser.ts @@ -1,7 +1,6 @@ import * as vscode from 'vscode'; -import { SelfCodeObject } from './selfCodes'; -import { JDBCOptions } from '../../../connection/types'; import { JobManager } from '../../../config'; +import { SelfCodeObject } from './selfCodes'; export class SelfCodesQuickPickItem implements vscode.QuickPickItem { label: string; From cbfe95eee01fe620401a5edd97e96ce80ee8c720 Mon Sep 17 00:00:00 2001 From: ajshedivy Date: Tue, 17 Oct 2023 14:52:02 -0500 Subject: [PATCH 04/12] add get self codes option --- package.json | 14 +++++++++ src/testing/manager.ts | 41 ++++++++++++++++++++++++++ src/views/jobManager/jobManagerView.ts | 15 ++++++++++ 3 files changed, 70 insertions(+) diff --git a/package.json b/package.json index 618072ce..55fa284e 100644 --- a/package.json +++ b/package.json @@ -317,6 +317,11 @@ "title": "Get Trace Data", "category": "Db2 for i" }, + { + "command": "vscode-db2i.jobManager.getSelfErrors", + "title": "Get SELFCODES Errors", + "category": "Db2 for i" + }, { "command": "vscode-db2i.jobManager.newConfig", "title": "Save settings to config", @@ -370,6 +375,10 @@ "command": "vscode-db2i.jobManager.enableTracing", "when": "never" }, + { + "command": "vscode-db2i.jobManager.getSelfErrors", + "when": "never" + }, { "command": "vscode-db2i.jobManager.getTrace", "when": "never" @@ -554,6 +563,11 @@ "when": "view == jobManager && viewItem == sqlJob", "group": "trace@2" }, + { + "command": "vscode-db2i.jobManager.getSelfErrors", + "when": "view == jobManager && viewItem == sqlJob", + "group": "trace@3" + }, { "command": "vscode-db2i.jobManager.newConfig", "when": "view == jobManager && viewItem == sqlJob", diff --git a/src/testing/manager.ts b/src/testing/manager.ts index 258a7dc0..b57253f5 100644 --- a/src/testing/manager.ts +++ b/src/testing/manager.ts @@ -3,6 +3,7 @@ import { TestSuite } from "."; import { JobManager } from "../config"; import { ServerComponent } from "../connection/serverComponent"; import { JobStatus } from "../connection/sqlJob"; +import { setSelfCodes } from "../views/jobManager/selfCodes/selfCodesBrowser"; export const ManagerSuite: TestSuite = { name: `Job manager tests`, @@ -91,5 +92,45 @@ export const ManagerSuite: TestSuite = { await JobManager.endAll(); }}, + {name: `Get SELFCODES Errors`, test: async () => { + assert.strictEqual(ServerComponent.isInstalled(), true); + + // Ensure we have a blank manager first + await JobManager.endAll(); + assert.strictEqual(JobManager.getRunningJobs().length, 0); + assert.strictEqual(JobManager.selectedJob, -1); + + // Add a new job + await JobManager.newJob(); + + // Check the job exists + assert.strictEqual(JobManager.getRunningJobs().length, 1); + + const curJob = JobManager.getRunningJobs(); + + // set self codes + setSelfCodes(['138', '180']) + + // SQL0138, get left-most 1001 characters of C2. C2 is only 100 characters long, so SQL0138 is produced + const sqlTestChar = `SELECT LEFT(C2, 1001) FROM SELFTEST.MYTBL` + + await JobManager.runSQL(sqlTestChar); + + const content = `SELECT * FROM QSYS2.SQL_ERROR_LOG WHERE JOB_NAME = '${curJob[0].job.id}'`; + + const data = await JobManager.runSQL(content); + + assert.strictEqual(data.length, 1); + + // SQL0180, invalid format for date given + const sqltestDate = `VALUES DATE('120-1231-12312')`; + + await JobManager.runSQL(sqltestDate); + + const newData = await JobManager.runSQL(content); + + assert.strictEqual(newData.length, 2); + + }} ] } \ No newline at end of file diff --git a/src/views/jobManager/jobManagerView.ts b/src/views/jobManager/jobManagerView.ts index 74b190dc..c6a7cfc5 100644 --- a/src/views/jobManager/jobManagerView.ts +++ b/src/views/jobManager/jobManagerView.ts @@ -184,6 +184,21 @@ export class JobManagerView implements TreeDataProvider { } }), + vscode.commands.registerCommand(`vscode-db2i.jobManager.getSelfErrors`, async (node?: SQLJobItem) => { + if (node) { + const id = node.label as string; + const selected = await JobManager.getJob(id); + + const content = `SELECT * FROM QSYS2.SQL_ERROR_LOG WHERE JOB_NAME = '${selected.job.id}'`; + + vscode.commands.executeCommand(`vscode-db2i.runEditorStatement`, { + content, + qualifier: `statement`, + open: false, + }); + } + }), + vscode.commands.registerCommand(`vscode-db2i.jobManager.enableTracing`, async (node?: SQLJobItem) => { if (node) { const id = node.label as string; From ebcaf56231c6b5756172e4ca40ae875b19804295 Mon Sep 17 00:00:00 2001 From: ajshedivy Date: Wed, 18 Oct 2023 12:49:43 -0500 Subject: [PATCH 05/12] edit self code label --- package.json | 4 ++-- src/testing/manager.ts | 2 +- src/views/jobManager/jobManagerView.ts | 6 +++--- src/views/jobManager/selfCodes/selfCodesBrowser.ts | 2 +- src/views/jobManager/statusBar.ts | 2 +- 5 files changed, 8 insertions(+), 8 deletions(-) diff --git a/package.json b/package.json index 55fa284e..bc199761 100644 --- a/package.json +++ b/package.json @@ -291,7 +291,7 @@ }, { "command": "vscode-db2i.jobManager.editSelfCodes", - "title": "Edit SELFCODES", + "title": "Edit SELF codes", "category": "Db2 for i", "icon": "$(bracket-error)" }, @@ -319,7 +319,7 @@ }, { "command": "vscode-db2i.jobManager.getSelfErrors", - "title": "Get SELFCODES Errors", + "title": "Get SELF codes Errors", "category": "Db2 for i" }, { diff --git a/src/testing/manager.ts b/src/testing/manager.ts index b57253f5..fae2d930 100644 --- a/src/testing/manager.ts +++ b/src/testing/manager.ts @@ -92,7 +92,7 @@ export const ManagerSuite: TestSuite = { await JobManager.endAll(); }}, - {name: `Get SELFCODES Errors`, test: async () => { + {name: `Get SELF codes Errors`, test: async () => { assert.strictEqual(ServerComponent.isInstalled(), true); // Ensure we have a blank manager first diff --git a/src/views/jobManager/jobManagerView.ts b/src/views/jobManager/jobManagerView.ts index c6a7cfc5..9ea5e624 100644 --- a/src/views/jobManager/jobManagerView.ts +++ b/src/views/jobManager/jobManagerView.ts @@ -144,18 +144,18 @@ export class JobManagerView implements TreeDataProvider { ); const quickPick = vscode.window.createQuickPick(); - quickPick.title = `Select SELFCODES`; + quickPick.title = `Select SELF codes`; quickPick.canSelectMany = true; quickPick.matchOnDetail = true; quickPick.items = [ { kind: vscode.QuickPickItemKind.Separator, - label: "Currently selected SELFCODES", + label: "Currently selected SELF codes", }, ...currentSelfCodeItems, { kind: vscode.QuickPickItemKind.Separator, - label: "All Available SELFCODES", + label: "All Available SELF codes", }, ...selfCodeItems.filter((item) => currentSelfCodeItems diff --git a/src/views/jobManager/selfCodes/selfCodesBrowser.ts b/src/views/jobManager/selfCodes/selfCodesBrowser.ts index 5053e0ef..a90e663e 100644 --- a/src/views/jobManager/selfCodes/selfCodesBrowser.ts +++ b/src/views/jobManager/selfCodes/selfCodesBrowser.ts @@ -17,7 +17,7 @@ export async function setSelfCodes(codes: string[]) { try { await JobManager.runSQL(`SET SYSIBMADM.SELFCODES = SYSIBMADM.VALIDATE_SELF('${codes.join(', ')}')`); - vscode.window.showInformationMessage(`Applied SELFCODES: ${codes}`); + vscode.window.showInformationMessage(`Applied SELF codes: ${codes}`); } catch (e) { vscode.window.showErrorMessage(e.message); } diff --git a/src/views/jobManager/statusBar.ts b/src/views/jobManager/statusBar.ts index 9cf0516e..eef440e5 100644 --- a/src/views/jobManager/statusBar.ts +++ b/src/views/jobManager/statusBar.ts @@ -33,7 +33,7 @@ export async function updateStatusBar() { toolTipItems.push(`[$(info) View Job Log](command:vscode-db2i.jobManager.viewJobLog)`); toolTipItems.push(`[$(edit) Edit Connection Settings](command:vscode-db2i.jobManager.editJobProps)`); - toolTipItems.push(`[$(bracket-error) Edit SELFCODES](command:vscode-db2i.jobManager.editSelfCodes)`); + toolTipItems.push(`[$(bracket-error) Edit SELF codes](command:vscode-db2i.jobManager.editSelfCodes)`); } else { text = `$(database) No job active`; toolTipItems.push(`[Start Job](command:vscode-db2i.jobManager.newJob)`); From bd76b152f080ee39064e82b4ba1dbd03e97e1337 Mon Sep 17 00:00:00 2001 From: ajshedivy Date: Wed, 18 Oct 2023 13:22:07 -0500 Subject: [PATCH 06/12] move set self codes to SQL job --- src/connection/sqlJob.ts | 10 +++++++++ src/testing/manager.ts | 5 ++--- src/views/jobManager/jobManagerView.ts | 21 +++++++++---------- .../jobManager/selfCodes/selfCodesBrowser.ts | 10 --------- 4 files changed, 22 insertions(+), 24 deletions(-) diff --git a/src/connection/sqlJob.ts b/src/connection/sqlJob.ts index 23de7741..77784b19 100644 --- a/src/connection/sqlJob.ts +++ b/src/connection/sqlJob.ts @@ -230,6 +230,16 @@ export class SQLJob { return rpy; } + async setSelfCodes(codes: string[]) { + try { + const query: string = `SET SYSIBMADM.SELFCODES = SYSIBMADM.VALIDATE_SELF('${codes.join(', ')}')` + await this.query(query).run(); + this.options.selfcodes = codes; + } catch (e) { + throw e; + } + } + async setTraceConfig(dest: ServerTraceDest, level: ServerTraceLevel): Promise { const reqObj = { id: SQLJob.getNewUniqueId(), diff --git a/src/testing/manager.ts b/src/testing/manager.ts index fae2d930..b29174e8 100644 --- a/src/testing/manager.ts +++ b/src/testing/manager.ts @@ -2,8 +2,7 @@ import assert from "assert"; import { TestSuite } from "."; import { JobManager } from "../config"; import { ServerComponent } from "../connection/serverComponent"; -import { JobStatus } from "../connection/sqlJob"; -import { setSelfCodes } from "../views/jobManager/selfCodes/selfCodesBrowser"; +import { JobStatus, SQLJob } from "../connection/sqlJob"; export const ManagerSuite: TestSuite = { name: `Job manager tests`, @@ -109,7 +108,7 @@ export const ManagerSuite: TestSuite = { const curJob = JobManager.getRunningJobs(); // set self codes - setSelfCodes(['138', '180']) + curJob[0].job.setSelfCodes(['138', '180']) // SQL0138, get left-most 1001 characters of C2. C2 is only 100 characters long, so SQL0138 is produced const sqlTestChar = `SELECT LEFT(C2, 1001) FROM SELFTEST.MYTBL` diff --git a/src/views/jobManager/jobManagerView.ts b/src/views/jobManager/jobManagerView.ts index 9ea5e624..fb03cbba 100644 --- a/src/views/jobManager/jobManagerView.ts +++ b/src/views/jobManager/jobManagerView.ts @@ -1,16 +1,15 @@ -import vscode, { MarkdownString, ProgressLocation, ThemeIcon, TreeItem, TreeItemCollapsibleState, Uri, commands, env, window, workspace } from "vscode"; -import { TreeDataProvider } from "vscode"; -import { Config, JobManager } from "../../config"; -import { JobInfo, SQLJobManager } from "../../connection/manager"; -import { editJobUi } from "./editJob"; -import { displayJobLog } from "./jobLog"; -import { ServerTraceDest, ServerTraceLevel } from "../../connection/types"; +import vscode, { ProgressLocation, TreeDataProvider, TreeItemCollapsibleState, Uri, commands, env, window } from "vscode"; +import { JobManager } from "../../config"; +import { JobInfo } from "../../connection/manager"; import { ServerComponent } from "../../connection/serverComponent"; -import { updateStatusBar } from "./statusBar"; import { SQLJob, TransactionEndType } from "../../connection/sqlJob"; +import { ServerTraceDest, ServerTraceLevel } from "../../connection/types"; import { ConfigGroup, ConfigManager } from "./ConfigManager"; +import { editJobUi } from "./editJob"; +import { displayJobLog } from "./jobLog"; import { selfCodesMap } from "./selfCodes/selfCodes"; -import { SelfCodesQuickPickItem, setSelfCodes } from "./selfCodes/selfCodesBrowser"; +import { SelfCodesQuickPickItem } from "./selfCodes/selfCodesBrowser"; +import { updateStatusBar } from "./statusBar"; const selectJobCommand = `vscode-db2i.jobManager.selectJob`; const activeColor = new vscode.ThemeColor(`minimapGutter.addedBackground`); @@ -171,8 +170,8 @@ export class JobManagerView implements TreeDataProvider { // SET SYSIBMADM.SELFCODES = SYSIBMADM.VALIDATE_SELF('-514, -204, -501, +30, -199'); if (selections) { const codes: string[] = selections.map((code) => code.label); - setSelfCodes(codes); - selected.job.options.selfcodes = codes; + selected.job.setSelfCodes(codes); + vscode.window.showInformationMessage(`Applied SELF codes: ${codes}`); } quickPick.hide(); }); diff --git a/src/views/jobManager/selfCodes/selfCodesBrowser.ts b/src/views/jobManager/selfCodes/selfCodesBrowser.ts index a90e663e..a4176754 100644 --- a/src/views/jobManager/selfCodes/selfCodesBrowser.ts +++ b/src/views/jobManager/selfCodes/selfCodesBrowser.ts @@ -11,14 +11,4 @@ export class SelfCodesQuickPickItem implements vscode.QuickPickItem { this.label = object.code; this.description = object.message; } -} - -export async function setSelfCodes(codes: string[]) { - try { - await JobManager.runSQL(`SET SYSIBMADM.SELFCODES = SYSIBMADM.VALIDATE_SELF('${codes.join(', ')}')`); - - vscode.window.showInformationMessage(`Applied SELF codes: ${codes}`); - } catch (e) { - vscode.window.showErrorMessage(e.message); - } } \ No newline at end of file From ebb847e29dd6360fe797a220364252a94a687db1 Mon Sep 17 00:00:00 2001 From: ajshedivy Date: Thu, 19 Oct 2023 11:01:39 -0500 Subject: [PATCH 07/12] add more tests --- src/testing/manager.ts | 27 +----- .../jobManager/selfCodes/selfCodesTest.ts | 95 +++++++++++++++++++ 2 files changed, 98 insertions(+), 24 deletions(-) create mode 100644 src/views/jobManager/selfCodes/selfCodesTest.ts diff --git a/src/testing/manager.ts b/src/testing/manager.ts index b29174e8..f92cd7d7 100644 --- a/src/testing/manager.ts +++ b/src/testing/manager.ts @@ -3,6 +3,7 @@ import { TestSuite } from "."; import { JobManager } from "../config"; import { ServerComponent } from "../connection/serverComponent"; import { JobStatus, SQLJob } from "../connection/sqlJob"; +import { testSelfCodes } from "../views/jobManager/selfCodes/selfCodesTest"; export const ManagerSuite: TestSuite = { name: `Job manager tests`, @@ -107,29 +108,7 @@ export const ManagerSuite: TestSuite = { const curJob = JobManager.getRunningJobs(); - // set self codes - curJob[0].job.setSelfCodes(['138', '180']) - - // SQL0138, get left-most 1001 characters of C2. C2 is only 100 characters long, so SQL0138 is produced - const sqlTestChar = `SELECT LEFT(C2, 1001) FROM SELFTEST.MYTBL` - - await JobManager.runSQL(sqlTestChar); - - const content = `SELECT * FROM QSYS2.SQL_ERROR_LOG WHERE JOB_NAME = '${curJob[0].job.id}'`; - - const data = await JobManager.runSQL(content); - - assert.strictEqual(data.length, 1); - - // SQL0180, invalid format for date given - const sqltestDate = `VALUES DATE('120-1231-12312')`; - - await JobManager.runSQL(sqltestDate); - - const newData = await JobManager.runSQL(content); - - assert.strictEqual(newData.length, 2); - - }} + }}, + ...testSelfCodes() ] } \ No newline at end of file diff --git a/src/views/jobManager/selfCodes/selfCodesTest.ts b/src/views/jobManager/selfCodes/selfCodesTest.ts new file mode 100644 index 00000000..bbe3155f --- /dev/null +++ b/src/views/jobManager/selfCodes/selfCodesTest.ts @@ -0,0 +1,95 @@ +import { assert } from "vitest"; +import { JobManager } from "../../../config"; +import { TestCase } from "../../../testing"; + +export const selfCodeTests = [ + { + name: "SQL0138 - Left-most 1001 characters of C2", + code: "138", + sql: "SELECT LEFT(C2, 1001) FROM SELFTEST.MYTBL", + }, + { + name: "SQL0180 - Invalid format for date", + code: "180", + sql: "VALUES DATE('120-1231-12312')", + }, + { + name: "SQL0181 - Date that doesn't exist", + code: "181", + sql: "VALUES DATE('2023-45-45')", + }, + { + name: "SQL0182 - Valid datetime, invalid context", + code: "182", + sql: "SELECT C3/C4 FROM SELFTEST.MYTBL", + }, + { + name: "SQL0199 - Invalid syntax", + code: "199", + sql: "SELECT * FROM SELFTEST.MYTBL WHERE ORDER BY C1", + }, + { + name: "SQL0203 - C2 without table name", + code: "203", + sql: "SELECT SELFTEST.MYTBL.C2 FROM SELFTEST.MYTBL T1 JOIN SELFTEST.MYTBL2 T2 ON T1.C1 = T2.C1", + }, + { + name: "SQL0204 - Table doesn't exist", + code: "204", + sql: "SELECT * FROM NOEXIST", + }, + { + name: "SQL0206 - Column doesn't exist", + code: "206", + sql: "SELECT NOCOL FROM SELFTEST.MYTBL", + }, + { + name: "SQL0420 - Can't cast varchar to int", + code: "420", + sql: "SELECT CAST(SELFTEST.MYTBL.C2 AS INT) FROM SELFTEST.MYTBL", + }, + // this is a sqpecial case, need to think about how to test this one + // { + // name: 'SQL0551 - User profile NOGOOD has no authority', + // code: '551', + // sql: 'CL: CRTUSRPRF USRPRF(NOGOOD); SET SESSION AUTHORIZATION NOGOOD; SELECT * FROM SELFTEST.MYTBL2; DISCONNECT CURRENT; SET SCHEMA SELFTEST; CL: DLTUSRPRF USRPRF(NOGOOD);', + // }, + { + name: "SQL0811 - Subquery returns multiple rows", + code: "811", + sql: "UPDATE SELFTEST.MYTBL SET C1 = (SELECT C1 FROM SELFTEST.MYTBL2)", + }, +]; + +export function testSelfCodes(): TestCase[] { + let tests: TestCase[] = []; + for (const test of selfCodeTests) { + const testCase: TestCase = { + name: `Self code Error for test ${test.name}`, + test: async () => { + // Ensure we have a blank manager first + await JobManager.endAll(); + assert.strictEqual(JobManager.getRunningJobs().length, 0); + assert.strictEqual(JobManager.selectedJob, -1); + + // Add a new job + await JobManager.newJob(); + + // Check the job exists + assert.strictEqual(JobManager.getRunningJobs().length, 1); + + const curJob = JobManager.getRunningJobs(); + curJob[0].job.setSelfCodes([test.code]); + + const result = await JobManager.runSQL(test.sql); + + const content = `SELECT * FROM QSYS2.SQL_ERROR_LOG WHERE JOB_NAME = '${curJob[0].job.id}'`; + const data = await JobManager.runSQL(content); + + assert.strictEqual(data.length, 1); + }, + }; + tests.push(testCase); + } + return tests; +} From 7c3126cfc7f4d0f0b07f7580dc021c04044fd67f Mon Sep 17 00:00:00 2001 From: ajshedivy Date: Thu, 19 Oct 2023 14:17:45 -0500 Subject: [PATCH 08/12] set negative codes --- src/connection/sqlJob.ts | 3 ++- src/views/jobManager/selfCodes/selfCodesTest.ts | 9 ++++++--- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/src/connection/sqlJob.ts b/src/connection/sqlJob.ts index 77784b19..f5629b53 100644 --- a/src/connection/sqlJob.ts +++ b/src/connection/sqlJob.ts @@ -231,8 +231,9 @@ export class SQLJob { } async setSelfCodes(codes: string[]) { + const signedCodes: String[] = codes.map(code => [code, `-${code}`]).flat(); try { - const query: string = `SET SYSIBMADM.SELFCODES = SYSIBMADM.VALIDATE_SELF('${codes.join(', ')}')` + const query: string = `SET SYSIBMADM.SELFCODES = SYSIBMADM.VALIDATE_SELF('${signedCodes.join(', ')}')` await this.query(query).run(); this.options.selfcodes = codes; } catch (e) { diff --git a/src/views/jobManager/selfCodes/selfCodesTest.ts b/src/views/jobManager/selfCodes/selfCodesTest.ts index bbe3155f..f863dbb8 100644 --- a/src/views/jobManager/selfCodes/selfCodesTest.ts +++ b/src/views/jobManager/selfCodes/selfCodesTest.ts @@ -31,7 +31,7 @@ export const selfCodeTests = [ { name: "SQL0203 - C2 without table name", code: "203", - sql: "SELECT SELFTEST.MYTBL.C2 FROM SELFTEST.MYTBL T1 JOIN SELFTEST.MYTBL2 T2 ON T1.C1 = T2.C1", + sql: "SELECT C2 FROM SELFTEST.MYTBL T1 JOIN SELFTEST.MYTBL2 T2 ON T1.C1 = T2.C1", }, { name: "SQL0204 - Table doesn't exist", @@ -80,8 +80,11 @@ export function testSelfCodes(): TestCase[] { const curJob = JobManager.getRunningJobs(); curJob[0].job.setSelfCodes([test.code]); - - const result = await JobManager.runSQL(test.sql); + try { + const result = await JobManager.runSQL(test.sql); + } catch (e) { + // handle the exception here + } const content = `SELECT * FROM QSYS2.SQL_ERROR_LOG WHERE JOB_NAME = '${curJob[0].job.id}'`; const data = await JobManager.runSQL(content); From 44ca29407e6fa73d390f8f661d0d662f00045264 Mon Sep 17 00:00:00 2001 From: Adam Shedivy Date: Fri, 20 Oct 2023 11:09:25 -0500 Subject: [PATCH 09/12] use sqljob api directly in tests --- src/testing/jobs.ts | 2 ++ src/testing/manager.ts | 20 +---------- .../jobManager/selfCodes/selfCodesTest.ts | 34 ++++++------------- 3 files changed, 14 insertions(+), 42 deletions(-) diff --git a/src/testing/jobs.ts b/src/testing/jobs.ts index 850f3c51..012088ca 100644 --- a/src/testing/jobs.ts +++ b/src/testing/jobs.ts @@ -5,6 +5,7 @@ import { getInstance } from "../base"; import { ServerComponent } from "../connection/serverComponent"; import { ServerTraceDest, ServerTraceLevel } from "../connection/types"; import { Query } from "../connection/query"; +import { testSelfCodes } from "../views/jobManager/selfCodes/selfCodesTest"; export const JobsSuite: TestSuite = { name: `Connection tests`, @@ -418,5 +419,6 @@ export const JobsSuite: TestSuite = { console.log(`Old query method took ${oe - os} milliseconds.`); assert.equal((ne - ns) < (oe - os), true); }}, + ...testSelfCodes() ] } \ No newline at end of file diff --git a/src/testing/manager.ts b/src/testing/manager.ts index f92cd7d7..4e10ba5a 100644 --- a/src/testing/manager.ts +++ b/src/testing/manager.ts @@ -91,24 +91,6 @@ export const ManagerSuite: TestSuite = { assert.strictEqual(JobManager.getSelection().name, runningJobs[0].name); await JobManager.endAll(); - }}, - {name: `Get SELF codes Errors`, test: async () => { - assert.strictEqual(ServerComponent.isInstalled(), true); - - // Ensure we have a blank manager first - await JobManager.endAll(); - assert.strictEqual(JobManager.getRunningJobs().length, 0); - assert.strictEqual(JobManager.selectedJob, -1); - - // Add a new job - await JobManager.newJob(); - - // Check the job exists - assert.strictEqual(JobManager.getRunningJobs().length, 1); - - const curJob = JobManager.getRunningJobs(); - - }}, - ...testSelfCodes() + }} ] } \ No newline at end of file diff --git a/src/views/jobManager/selfCodes/selfCodesTest.ts b/src/views/jobManager/selfCodes/selfCodesTest.ts index f863dbb8..f3c06d28 100644 --- a/src/views/jobManager/selfCodes/selfCodesTest.ts +++ b/src/views/jobManager/selfCodes/selfCodesTest.ts @@ -1,6 +1,6 @@ -import { assert } from "vitest"; -import { JobManager } from "../../../config"; +import { SQLJob } from "../../../connection/sqlJob"; import { TestCase } from "../../../testing"; +import assert from "assert"; export const selfCodeTests = [ { @@ -67,29 +67,17 @@ export function testSelfCodes(): TestCase[] { const testCase: TestCase = { name: `Self code Error for test ${test.name}`, test: async () => { - // Ensure we have a blank manager first - await JobManager.endAll(); - assert.strictEqual(JobManager.getRunningJobs().length, 0); - assert.strictEqual(JobManager.selectedJob, -1); - - // Add a new job - await JobManager.newJob(); - - // Check the job exists - assert.strictEqual(JobManager.getRunningJobs().length, 1); - - const curJob = JobManager.getRunningJobs(); - curJob[0].job.setSelfCodes([test.code]); + let newJob = new SQLJob(); + await newJob.connect(); + await newJob.setSelfCodes([test.code]); try { - const result = await JobManager.runSQL(test.sql); - } catch (e) { - // handle the exception here - } - - const content = `SELECT * FROM QSYS2.SQL_ERROR_LOG WHERE JOB_NAME = '${curJob[0].job.id}'`; - const data = await JobManager.runSQL(content); + await newJob.query(test.sql).run(); + } catch (e) {} - assert.strictEqual(data.length, 1); + const content = `SELECT * FROM QSYS2.SQL_ERROR_LOG WHERE JOB_NAME = '${newJob.id}'`; + let errors = await newJob.query(content).run(); + assert.strictEqual(errors.data.length, 1); + newJob.close(); }, }; tests.push(testCase); From 82d0b519b4208d39d8d284a0d78361b99b501870 Mon Sep 17 00:00:00 2001 From: ajshedivy Date: Tue, 28 Nov 2023 13:56:15 -0600 Subject: [PATCH 10/12] move self code actions to right click --- package.json | 4 ++-- src/testing/manager.ts | 3 +-- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/package.json b/package.json index bc199761..0ca77a02 100644 --- a/package.json +++ b/package.json @@ -541,7 +541,7 @@ { "command": "vscode-db2i.jobManager.editSelfCodes", "when": "view == jobManager && viewItem == sqlJob", - "group": "inline" + "group": "self@2" }, { "command": "vscode-db2i.jobManager.copyJobId", @@ -566,7 +566,7 @@ { "command": "vscode-db2i.jobManager.getSelfErrors", "when": "view == jobManager && viewItem == sqlJob", - "group": "trace@3" + "group": "self@1" }, { "command": "vscode-db2i.jobManager.newConfig", diff --git a/src/testing/manager.ts b/src/testing/manager.ts index 4e10ba5a..9581cd05 100644 --- a/src/testing/manager.ts +++ b/src/testing/manager.ts @@ -2,8 +2,7 @@ import assert from "assert"; import { TestSuite } from "."; import { JobManager } from "../config"; import { ServerComponent } from "../connection/serverComponent"; -import { JobStatus, SQLJob } from "../connection/sqlJob"; -import { testSelfCodes } from "../views/jobManager/selfCodes/selfCodesTest"; +import { JobStatus } from "../connection/sqlJob"; export const ManagerSuite: TestSuite = { name: `Job manager tests`, From dfd8f6819410a3cc108d973729f4fd3cb41158f5 Mon Sep 17 00:00:00 2001 From: ajshedivy Date: Tue, 28 Nov 2023 14:18:39 -0600 Subject: [PATCH 11/12] put tests in their own suite --- src/testing/index.ts | 2 ++ src/testing/jobs.ts | 6 ++---- src/testing/selfCodes.ts | 7 +++++++ 3 files changed, 11 insertions(+), 4 deletions(-) create mode 100644 src/testing/selfCodes.ts diff --git a/src/testing/index.ts b/src/testing/index.ts index e0502270..9ced9d10 100644 --- a/src/testing/index.ts +++ b/src/testing/index.ts @@ -6,9 +6,11 @@ import { ManagerSuite } from "./manager"; import { JobsSuite } from "./jobs"; import { DatabaseSuite } from "./database"; import { DatabasePerformanceSuite } from "./databasePerformance"; +import { SelfCodesTestSuite } from "./selfCodes"; const suites : TestSuite[] = [ JobsSuite, + SelfCodesTestSuite, ManagerSuite, DatabaseSuite, DatabasePerformanceSuite diff --git a/src/testing/jobs.ts b/src/testing/jobs.ts index 012088ca..e4c4d0c6 100644 --- a/src/testing/jobs.ts +++ b/src/testing/jobs.ts @@ -1,11 +1,10 @@ import assert from "assert"; import { TestSuite } from "."; -import { JobStatus, SQLJob } from "../connection/sqlJob"; import { getInstance } from "../base"; +import { Query } from "../connection/query"; import { ServerComponent } from "../connection/serverComponent"; +import { JobStatus, SQLJob } from "../connection/sqlJob"; import { ServerTraceDest, ServerTraceLevel } from "../connection/types"; -import { Query } from "../connection/query"; -import { testSelfCodes } from "../views/jobManager/selfCodes/selfCodesTest"; export const JobsSuite: TestSuite = { name: `Connection tests`, @@ -419,6 +418,5 @@ export const JobsSuite: TestSuite = { console.log(`Old query method took ${oe - os} milliseconds.`); assert.equal((ne - ns) < (oe - os), true); }}, - ...testSelfCodes() ] } \ No newline at end of file diff --git a/src/testing/selfCodes.ts b/src/testing/selfCodes.ts new file mode 100644 index 00000000..4614ca49 --- /dev/null +++ b/src/testing/selfCodes.ts @@ -0,0 +1,7 @@ +import { TestSuite } from "."; +import { testSelfCodes } from "../views/jobManager/selfCodes/selfCodesTest"; + +export const SelfCodesTestSuite: TestSuite = { + name: `Self Codes Tests`, + tests: [...testSelfCodes()] +} \ No newline at end of file From 4e9890ad46cbaa6e508af60a4927aec1eb3d69de Mon Sep 17 00:00:00 2001 From: ajshedivy Date: Tue, 28 Nov 2023 14:59:19 -0600 Subject: [PATCH 12/12] add test schema setup to tests --- src/testing/selfCodes.ts | 39 ++++++++++++++++++++++++++++++++++++++- 1 file changed, 38 insertions(+), 1 deletion(-) diff --git a/src/testing/selfCodes.ts b/src/testing/selfCodes.ts index 4614ca49..659ac4e6 100644 --- a/src/testing/selfCodes.ts +++ b/src/testing/selfCodes.ts @@ -1,7 +1,44 @@ +import assert from "assert"; import { TestSuite } from "."; +import { ServerComponent } from "../connection/serverComponent"; import { testSelfCodes } from "../views/jobManager/selfCodes/selfCodesTest"; +import { getInstance } from "../base"; export const SelfCodesTestSuite: TestSuite = { name: `Self Codes Tests`, - tests: [...testSelfCodes()] + tests: [ + {name: `Backend check`, test: async () => { + const backendInstalled = await ServerComponent.initialise(); + + // To run these tests, we need the backend server. If this test fails. Don't bother + assert.strictEqual(backendInstalled, true); + try { + const selfTestSchema = [ + `CREATE SCHEMA SELFTEST;`, + ``, + `CREATE OR REPLACE TABLE SELFTEST.MYTBL (C1 INT, C2 VARCHAR(100), C3 TIMESTAMP, C4 DATE);`, + ``, + `CREATE OR REPLACE TABLE SELFTEST.MYTBL2 (C1 INT, C2 VARCHAR(100), C3 TIMESTAMP, C4 DATE);`, + ``, + `INSERT INTO SELFTEST.MYTBL VALUES (0, 'ADAM', CURRENT TIMESTAMP, CURRENT DATE);`, + ``, + `INSERT INTO SELFTEST.MYTBL VALUES (1, 'LIAM', CURRENT TIMESTAMP + 1 SECOND, CURRENT DATE + 1 DAY);`, + ``, + `INSERT INTO SELFTEST.MYTBL VALUES (2, 'RYAN', CURRENT TIMESTAMP + 2 SECOND, CURRENT DATE + 2 DAY);`, + ``, + `INSERT INTO SELFTEST.MYTBL VALUES (3, NULL, CURRENT TIMESTAMP + 2 SECOND, CURRENT DATE + 2 DAY);`, + ``, + `INSERT INTO SELFTEST.MYTBL2 VALUES (0, 'TIM', CURRENT TIMESTAMP, CURRENT DATE);`, + ``, + `INSERT INTO SELFTEST.MYTBL2 VALUES (1, 'SCOTT', CURRENT TIMESTAMP + 1 SECOND, CURRENT DATE + 1 DAY);`, + ``, + `INSERT INTO SELFTEST.MYTBL2 VALUES (2, 'JESSIE', CURRENT TIMESTAMP + 2 SECOND, CURRENT DATE + 2 DAY);` + ] + await getInstance().getContent().runSQL(selfTestSchema.join(`\n`)); + + } catch (e) { + console.log(`Possible fail`); + } + }}, + ...testSelfCodes()] } \ No newline at end of file