From 4b6430789af53a875acf596d3bfaecb1d7bf60cf Mon Sep 17 00:00:00 2001 From: Adam Shedivy Date: Tue, 3 Dec 2024 13:30:27 -0600 Subject: [PATCH 01/17] fix column null context --- src/aiProviders/continue/continueContextProvider.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/aiProviders/continue/continueContextProvider.ts b/src/aiProviders/continue/continueContextProvider.ts index 6f08f8a5..117c9a32 100644 --- a/src/aiProviders/continue/continueContextProvider.ts +++ b/src/aiProviders/continue/continueContextProvider.ts @@ -148,7 +148,7 @@ export class db2ContextProvider implements IContextProvider { const columnData: TableColumn[] = tableRefs[table]; if (columnData && columnData.length > 0) { const tableSchema = - columnData.length > 0 ? columnData[0].TABLE_SCHEMA : null; + columnData[0].TABLE_SCHEMA ?? schema; // create context item let prompt = `Db2 for i Table meta data for schema ${tableSchema} table ${table}\n`; From 171f67936003db5db8004866320164239dba95ef Mon Sep 17 00:00:00 2001 From: Adam Shedivy Date: Fri, 13 Dec 2024 18:11:00 -0600 Subject: [PATCH 02/17] WIP: list tables context provider --- .../continue/continueContextProvider.ts | 43 +++++++++- .../continue/listTablesContextProvider.ts | 82 +++++++++++++++++++ src/extension.ts | 5 ++ 3 files changed, 126 insertions(+), 4 deletions(-) create mode 100644 src/aiProviders/continue/listTablesContextProvider.ts diff --git a/src/aiProviders/continue/continueContextProvider.ts b/src/aiProviders/continue/continueContextProvider.ts index 117c9a32..e1ce80d5 100644 --- a/src/aiProviders/continue/continueContextProvider.ts +++ b/src/aiProviders/continue/continueContextProvider.ts @@ -2,7 +2,7 @@ import * as vscode from "vscode"; import { JobManager } from "../../config"; import { JobInfo } from "../../connection/manager"; import { SelfCodeNode } from "../../views/jobManager/selfCodes/nodes"; -import { canTalkToDb, findPossibleTables } from "../context"; +import { canTalkToDb, findPossibleTables, TableRefs } from "../context"; import { ContextItem, ContextProviderDescription, @@ -12,6 +12,7 @@ import { LoadSubmenuItemsArgs, } from "@continuedev/core"; import { DB2_SELF_PROMPT, DB2_SYSTEM_PROMPT } from "./prompts"; +import { table } from "console"; export let isContinueActive = false; @@ -102,6 +103,25 @@ export class db2ContextProvider implements IContextProvider { } } + parseSelectedCode(fullInput: string): string | null { + const regex = /```(?:.*?\n)?(.*?)```/gs; + + // Extract matches + const matches = fullInput.match(regex); + + if (matches && matches.length > 0) { + // Extract SQL code from the first match + let sqlCode = matches[0].replace(/```(?:.*?\n)?|```/g, '').trim(); + // Remove all newline characters + sqlCode = sqlCode.replace(/[\r\n]+/g, ' ').trim(); + return sqlCode; + } + + // Return null if no SQL code is found + return null; +} + + async getContextItems( query: string, extras: ContextProviderExtras @@ -111,6 +131,10 @@ export class db2ContextProvider implements IContextProvider { const job: JobInfo = this.getCurrentJob(); const schema = this.getDefaultSchema(); const fullInput = extras.fullInput; + const selectedCode = extras.selectedCode; + if (selectedCode) { + const parsedCode = this.parseSelectedCode(fullInput); + } contextItems.push({ name: `SYSTEM PROMPT`, description: `system prompt context`, @@ -138,14 +162,25 @@ export class db2ContextProvider implements IContextProvider { return contextItems; default: - // const contextItems: ContextItem[] = []; + + // check for selected code refs since these are apart of markdown string + let selectedCodeRefs: TableRefs = {}; + if (selectedCode.length > 0) { + const parsedCode = this.parseSelectedCode(fullInput); + selectedCodeRefs = await findPossibleTables(null, schema, parsedCode.split(` `)); + } + + // check full input for table refs const tableRefs = await findPossibleTables( null, schema, fullInput.split(` `) ); - for (const table of Object.keys(tableRefs)) { - const columnData: TableColumn[] = tableRefs[table]; + + // Merge selectedCodeRefs into tableRefs + const mergedRefs = { ...tableRefs, ...selectedCodeRefs }; + for (const table of Object.keys(mergedRefs)) { + const columnData: TableColumn[] = mergedRefs[table]; if (columnData && columnData.length > 0) { const tableSchema = columnData[0].TABLE_SCHEMA ?? schema; diff --git a/src/aiProviders/continue/listTablesContextProvider.ts b/src/aiProviders/continue/listTablesContextProvider.ts new file mode 100644 index 00000000..68c4d804 --- /dev/null +++ b/src/aiProviders/continue/listTablesContextProvider.ts @@ -0,0 +1,82 @@ +import * as vscode from "vscode"; +import { ContextItem, ContextProviderDescription, ContextProviderExtras, ContextSubmenuItem, IContextProvider, LoadSubmenuItemsArgs } from "@continuedev/core"; +import { JobInfo } from "../../connection/manager"; +import { JobManager } from "../../config"; +import { isContinueActive } from "./continueContextProvider"; +import { findPossibleTables } from "../context"; + +const listDb2Table: ContextProviderDescription = { + title: "list Db2i Tables", + displayTitle: "Db2i-tables", + description: "Add Db2i Table info to Context", + type: "submenu" +} + +class ListDb2iTables implements IContextProvider { + get description(): ContextProviderDescription { + return listDb2Table + } + + getCurrentJob(): JobInfo { + const currentJob: JobInfo = JobManager.getSelection(); + return currentJob; + } + + private getDefaultSchema = (): string => { + const currentJob: JobInfo = this.getCurrentJob(); + return currentJob?.job.options.libraries[0] || "QGPL"; + } + + async getTables() { + const schema = this.getDefaultSchema().toUpperCase(); + const sql = ` + SELECT TABLE_NAME, TABLE_SCHEMA + FROM QSYS2.SYSTABLES + WHERE TABLE_SCHEMA = '${schema}' + AND TABLE_TYPE = 'T' + ORDER BY TABLE_NAME + `; + + const result = await JobManager.runSQL(sql); + return result; + + + } + + async getContextItems(query: string, extras: ContextProviderExtras): Promise { + const tableInfo = await findPossibleTables(null, this.getDefaultSchema(), query.split(` `)); + return [{ + name: `${query}`, + content: JSON.stringify(tableInfo), + description: "table metadata" + + }] + } + async loadSubmenuItems(args: LoadSubmenuItemsArgs): Promise { + const tables: any[] = await this.getTables(); + + return tables.map((table) => { + return { + id: table.TABLE_NAME, + title: table.TABLE_NAME, + description: `${table.TABLE_SCHEMA}-${table.TABLE_NAME}`, + } + }) + + } + +} + +export async function registerDb2iTablesProvider() { + const provider = new ListDb2iTables(); + const continueID = `Continue.continue`; + const continueEx = vscode.extensions.getExtension(continueID); + if (continueEx) { + if (!continueEx.isActive) { + await continueEx.activate(); + } + + const continueAPI = continueEx?.exports; + continueAPI?.registerCustomContextProvider(provider); + } +} \ No newline at end of file diff --git a/src/extension.ts b/src/extension.ts index 2138f7c7..ed5782a9 100644 --- a/src/extension.ts +++ b/src/extension.ts @@ -24,6 +24,7 @@ import { SelfTreeDecorationProvider, selfCodesResultsView } from "./views/jobMan import { registerContinueProvider } from "./aiProviders/continue/continueContextProvider"; import { queryHistory } from "./views/queryHistoryView"; import { activateChat, registerCopilotProvider } from "./aiProviders/copilot"; +import { registerDb2iTablesProvider } from "./aiProviders/continue/listTablesContextProvider"; export interface Db2i { sqlJobManager: SQLJobManager, @@ -98,6 +99,8 @@ export function activate(context: vscode.ExtensionContext): Db2i { onConnectOrServerInstall().then(() => { exampleBrowser.refresh(); selfCodesView.setRefreshEnabled(Configuration.get(`jobSelfViewAutoRefresh`) || false); + // register list tables + registerDb2iTablesProvider(); if (devMode && runTests) { runTests(); } @@ -110,6 +113,8 @@ export function activate(context: vscode.ExtensionContext): Db2i { // register continue provider registerContinueProvider(); + + instance.subscribe(context, `disconnected`, `db2i-disconnected`, () => ServerComponent.reset()); return { sqlJobManager: JobManager, sqlJob: (options?: JDBCOptions) => new OldSQLJob(options) }; From 437988885c206d17d4aeb9da111544d98898c37c Mon Sep 17 00:00:00 2001 From: Adam Shedivy Date: Mon, 16 Dec 2024 17:10:32 -0600 Subject: [PATCH 03/17] add schema context item to menu --- .../continue/listTablesContextProvider.ts | 49 ++++++++++++++----- 1 file changed, 38 insertions(+), 11 deletions(-) diff --git a/src/aiProviders/continue/listTablesContextProvider.ts b/src/aiProviders/continue/listTablesContextProvider.ts index 68c4d804..e5abfff9 100644 --- a/src/aiProviders/continue/listTablesContextProvider.ts +++ b/src/aiProviders/continue/listTablesContextProvider.ts @@ -4,6 +4,7 @@ import { JobInfo } from "../../connection/manager"; import { JobManager } from "../../config"; import { isContinueActive } from "./continueContextProvider"; import { findPossibleTables } from "../context"; +import Statement from "../../database/statement"; const listDb2Table: ContextProviderDescription = { title: "list Db2i Tables", @@ -27,8 +28,8 @@ class ListDb2iTables implements IContextProvider { return currentJob?.job.options.libraries[0] || "QGPL"; } - async getTables() { - const schema = this.getDefaultSchema().toUpperCase(); + async getTables(curSchema: string) { + const schema = Statement.delimName(curSchema, true); const sql = ` SELECT TABLE_NAME, TABLE_SCHEMA FROM QSYS2.SYSTABLES @@ -39,12 +40,31 @@ class ListDb2iTables implements IContextProvider { const result = await JobManager.runSQL(sql); return result; + } + + async getColumnInfoForAllTables(schema: string) { + const sql = ` + SELECT COLUMN_NAME, TABLE_NAME, DATA_TYPE + FROM QSYS2.SYSCOLUMNS + WHERE TABLE_SCHEMA = '${Statement.delimName(schema)}' + `; + const result = await JobManager.runSQL(sql); + return result; } async getContextItems(query: string, extras: ContextProviderExtras): Promise { - const tableInfo = await findPossibleTables(null, this.getDefaultSchema(), query.split(` `)); + const schema = this.getDefaultSchema(); + if (query.toUpperCase() === schema.toUpperCase()) { + const tableInfo = await this.getColumnInfoForAllTables(schema); + return [{ + name: `Info for all tables in ${schema}`, + content: JSON.stringify(tableInfo), + description: "table metadata" + }] + } + const tableInfo = await findPossibleTables(null, schema, query.split(` `)); return [{ name: `${query}`, content: JSON.stringify(tableInfo), @@ -52,17 +72,24 @@ class ListDb2iTables implements IContextProvider { }] } + async loadSubmenuItems(args: LoadSubmenuItemsArgs): Promise { - const tables: any[] = await this.getTables(); + const schema = this.getDefaultSchema(); + const tables: any[] = await this.getTables(schema); + + const schemaSubmenuItem: ContextSubmenuItem = { + id: schema, + title: schema, + description: `All table info in schema: ${schema}` + }; - return tables.map((table) => { - return { - id: table.TABLE_NAME, - title: table.TABLE_NAME, - description: `${table.TABLE_SCHEMA}-${table.TABLE_NAME}`, - } - }) + const tableSubmenuItems: ContextSubmenuItem[] = tables.map((table) => ({ + id: table.TABLE_NAME, + title: table.TABLE_NAME, + description: `${table.TABLE_SCHEMA}-${table.TABLE_NAME}`, + })); + return [schemaSubmenuItem, ...tableSubmenuItems]; } } From 8e7501fb1d5ee3cb4a14b31f70f1dea10d6cecf9 Mon Sep 17 00:00:00 2001 From: Adam Shedivy Date: Tue, 17 Dec 2024 13:24:52 -0600 Subject: [PATCH 04/17] use internal APIs for querying table meta data --- .../continue/continueContextProvider.ts | 47 ++-------- .../continue/listTablesContextProvider.ts | 89 +++++++++---------- src/database/table.ts | 10 ++- 3 files changed, 57 insertions(+), 89 deletions(-) diff --git a/src/aiProviders/continue/continueContextProvider.ts b/src/aiProviders/continue/continueContextProvider.ts index e1ce80d5..e2464b88 100644 --- a/src/aiProviders/continue/continueContextProvider.ts +++ b/src/aiProviders/continue/continueContextProvider.ts @@ -2,7 +2,7 @@ import * as vscode from "vscode"; import { JobManager } from "../../config"; import { JobInfo } from "../../connection/manager"; import { SelfCodeNode } from "../../views/jobManager/selfCodes/nodes"; -import { canTalkToDb, findPossibleTables, TableRefs } from "../context"; +import { canTalkToDb, findPossibleTables } from "../context"; import { ContextItem, ContextProviderDescription, @@ -12,7 +12,6 @@ import { LoadSubmenuItemsArgs, } from "@continuedev/core"; import { DB2_SELF_PROMPT, DB2_SYSTEM_PROMPT } from "./prompts"; -import { table } from "console"; export let isContinueActive = false; @@ -103,25 +102,6 @@ export class db2ContextProvider implements IContextProvider { } } - parseSelectedCode(fullInput: string): string | null { - const regex = /```(?:.*?\n)?(.*?)```/gs; - - // Extract matches - const matches = fullInput.match(regex); - - if (matches && matches.length > 0) { - // Extract SQL code from the first match - let sqlCode = matches[0].replace(/```(?:.*?\n)?|```/g, '').trim(); - // Remove all newline characters - sqlCode = sqlCode.replace(/[\r\n]+/g, ' ').trim(); - return sqlCode; - } - - // Return null if no SQL code is found - return null; -} - - async getContextItems( query: string, extras: ContextProviderExtras @@ -131,10 +111,6 @@ export class db2ContextProvider implements IContextProvider { const job: JobInfo = this.getCurrentJob(); const schema = this.getDefaultSchema(); const fullInput = extras.fullInput; - const selectedCode = extras.selectedCode; - if (selectedCode) { - const parsedCode = this.parseSelectedCode(fullInput); - } contextItems.push({ name: `SYSTEM PROMPT`, description: `system prompt context`, @@ -162,31 +138,20 @@ export class db2ContextProvider implements IContextProvider { return contextItems; default: - - // check for selected code refs since these are apart of markdown string - let selectedCodeRefs: TableRefs = {}; - if (selectedCode.length > 0) { - const parsedCode = this.parseSelectedCode(fullInput); - selectedCodeRefs = await findPossibleTables(null, schema, parsedCode.split(` `)); - } - - // check full input for table refs + // const contextItems: ContextItem[] = []; const tableRefs = await findPossibleTables( null, schema, fullInput.split(` `) ); - - // Merge selectedCodeRefs into tableRefs - const mergedRefs = { ...tableRefs, ...selectedCodeRefs }; - for (const table of Object.keys(mergedRefs)) { - const columnData: TableColumn[] = mergedRefs[table]; + for (const table of Object.keys(tableRefs)) { + const columnData: TableColumn[] = tableRefs[table]; if (columnData && columnData.length > 0) { const tableSchema = - columnData[0].TABLE_SCHEMA ?? schema; + columnData.length > 0 ? columnData[0].TABLE_SCHEMA : null; // create context item - let prompt = `Db2 for i Table meta data for schema ${tableSchema} table ${table}\n`; + let prompt = `Db2 for i table Assistant: The following information is based on the ${table} table within the ${tableSchema} schema. Utilize the provided schema and table metadata to assist the user:\n`; prompt += `Column Info: ${JSON.stringify(columnData)}\n\n`; contextItems.push({ diff --git a/src/aiProviders/continue/listTablesContextProvider.ts b/src/aiProviders/continue/listTablesContextProvider.ts index e5abfff9..745057ff 100644 --- a/src/aiProviders/continue/listTablesContextProvider.ts +++ b/src/aiProviders/continue/listTablesContextProvider.ts @@ -5,6 +5,8 @@ import { JobManager } from "../../config"; import { isContinueActive } from "./continueContextProvider"; import { findPossibleTables } from "../context"; import Statement from "../../database/statement"; +import Schemas from "../../database/schemas"; +import Table from "../../database/table"; const listDb2Table: ContextProviderDescription = { title: "list Db2i Tables", @@ -15,7 +17,7 @@ const listDb2Table: ContextProviderDescription = { class ListDb2iTables implements IContextProvider { get description(): ContextProviderDescription { - return listDb2Table + return listDb2Table; } getCurrentJob(): JobInfo { @@ -26,72 +28,69 @@ class ListDb2iTables implements IContextProvider { private getDefaultSchema = (): string => { const currentJob: JobInfo = this.getCurrentJob(); return currentJob?.job.options.libraries[0] || "QGPL"; - } - - async getTables(curSchema: string) { - const schema = Statement.delimName(curSchema, true); - const sql = ` - SELECT TABLE_NAME, TABLE_SCHEMA - FROM QSYS2.SYSTABLES - WHERE TABLE_SCHEMA = '${schema}' - AND TABLE_TYPE = 'T' - ORDER BY TABLE_NAME - `; - - const result = await JobManager.runSQL(sql); - return result; - } + }; async getColumnInfoForAllTables(schema: string) { - const sql = ` - SELECT COLUMN_NAME, TABLE_NAME, DATA_TYPE - FROM QSYS2.SYSCOLUMNS - WHERE TABLE_SCHEMA = '${Statement.delimName(schema)}' - `; - - const result = await JobManager.runSQL(sql); - return result; + const items: TableColumn[] = await Table.getItems(schema); + return items.map((column) => ({ + table_name: column.TABLE_NAME, + schema: column.TABLE_SCHEMA, + column_name: column.COLUMN_NAME, + column_data_type: column.DATA_TYPE, + })); } - async getContextItems(query: string, extras: ContextProviderExtras): Promise { + async getContextItems( + query: string, + extras: ContextProviderExtras + ): Promise { + let contextitems: ContextItem[] = []; const schema = this.getDefaultSchema(); if (query.toUpperCase() === schema.toUpperCase()) { const tableInfo = await this.getColumnInfoForAllTables(schema); - return [{ + contextitems.push({ name: `Info for all tables in ${schema}`, - content: JSON.stringify(tableInfo), - description: "table metadata" - }] + content: `Db2 for i table Assistant: The following table and column information is from the ${query} schema. Utilize the provided schema and table metadata to assist the user:\n${JSON.stringify(tableInfo)}`, + description: "table metadata", + }); + } else { + const tableInfo = await findPossibleTables( + null, + schema, + query.split(` `) + ); + contextitems.push({ + name: `${query}`, + content: `Db2 for i table Assistant: The following information is based on the ${query} table within the ${schema} schema. Utilize the provided schema and table metadata to assist the user:\n${JSON.stringify(tableInfo)}`, + description: "table metadata", + }); } - const tableInfo = await findPossibleTables(null, schema, query.split(` `)); - return [{ - name: `${query}`, - content: JSON.stringify(tableInfo), - description: "table metadata" - - }] + return contextitems; } - - async loadSubmenuItems(args: LoadSubmenuItemsArgs): Promise { + + async loadSubmenuItems( + args: LoadSubmenuItemsArgs + ): Promise { const schema = this.getDefaultSchema(); - const tables: any[] = await this.getTables(schema); - + const tables: BasicSQLObject[] = await Schemas.getObjects(schema, [ + `tables`, + ]); + const schemaSubmenuItem: ContextSubmenuItem = { id: schema, title: schema, - description: `All table info in schema: ${schema}` + description: `All table info in schema: ${schema}`, }; const tableSubmenuItems: ContextSubmenuItem[] = tables.map((table) => ({ - id: table.TABLE_NAME, - title: table.TABLE_NAME, - description: `${table.TABLE_SCHEMA}-${table.TABLE_NAME}`, + id: table.name, + title: table.name, + description: `${table.schema}-${table.name}`, })); return [schemaSubmenuItem, ...tableSubmenuItems]; } - } export async function registerDb2iTablesProvider() { diff --git a/src/database/table.ts b/src/database/table.ts index 06517510..91d3cf08 100644 --- a/src/database/table.ts +++ b/src/database/table.ts @@ -8,7 +8,8 @@ export default class Table { * @param {string} name Not user input * @returns {Promise} */ - static async getItems(schema: string, name: string): Promise { + static async getItems(schema: string, name?: string): Promise { + const params = name ? [schema, name] : [schema]; const sql = [ `SELECT `, ` column.TABLE_SCHEMA,`, @@ -30,11 +31,14 @@ export default class Table { ` column.table_schema = key.table_schema and`, ` column.table_name = key.table_name and`, ` column.column_name = key.column_name`, - `WHERE column.TABLE_SCHEMA = ? AND column.TABLE_NAME = ?`, + `WHERE column.TABLE_SCHEMA = ?`, + ...[ + name ? `AND column.TABLE_NAME = ${name}` : ``, + ], `ORDER BY column.ORDINAL_POSITION`, ].join(` `); - return JobManager.runSQL(sql, {parameters: [schema, name]}); + return JobManager.runSQL(sql, {parameters: params}); } /** From 76a600e5477a342a78c5a3362cacc43873e72286 Mon Sep 17 00:00:00 2001 From: Adam Shedivy Date: Fri, 20 Dec 2024 12:14:46 -0600 Subject: [PATCH 05/17] workaround for updating context provider schema --- .../continue/listTablesContextProvider.ts | 50 ++++++++++++++++++- src/views/jobManager/jobManagerView.ts | 4 ++ 2 files changed, 53 insertions(+), 1 deletion(-) diff --git a/src/aiProviders/continue/listTablesContextProvider.ts b/src/aiProviders/continue/listTablesContextProvider.ts index 745057ff..9e4a4d84 100644 --- a/src/aiProviders/continue/listTablesContextProvider.ts +++ b/src/aiProviders/continue/listTablesContextProvider.ts @@ -7,6 +7,9 @@ import { findPossibleTables } from "../context"; import Statement from "../../database/statement"; import Schemas from "../../database/schemas"; import Table from "../../database/table"; +import * as fs from 'fs'; +import * as path from 'path'; +import * as os from 'os'; const listDb2Table: ContextProviderDescription = { title: "list Db2i Tables", @@ -15,6 +18,8 @@ const listDb2Table: ContextProviderDescription = { type: "submenu" } +export let listDb2TableContextProvider: Boolean = false; + class ListDb2iTables implements IContextProvider { get description(): ContextProviderDescription { return listDb2Table; @@ -93,6 +98,24 @@ class ListDb2iTables implements IContextProvider { } } +class emptyContextProvider implements IContextProvider { + get description(): ContextProviderDescription { + return { + title: "", + displayTitle: "", + description: "", + type: "normal" + }; + } + async getContextItems(query: string, extras: ContextProviderExtras): Promise { + return []; + } + async loadSubmenuItems(args: LoadSubmenuItemsArgs): Promise { + return []; + } + +} + export async function registerDb2iTablesProvider() { const provider = new ListDb2iTables(); const continueID = `Continue.continue`; @@ -103,6 +126,31 @@ export async function registerDb2iTablesProvider() { } const continueAPI = continueEx?.exports; - continueAPI?.registerCustomContextProvider(provider); + if (listDb2TableContextProvider) { + + // HACK: re register context provider work around + // save continue config file to trigger a config reload to update list tables provider + const configFile = path.join(os.homedir(), `.continue`, `config.json`); + + fs.readFile(configFile, `utf-8`, (err, data) => { + if (err) { + console.error('Error reading Continue config file: ', err); + } + + const updatedData = data + ``; + + fs.writeFile(configFile, updatedData, `utf-8`, (err) => { + if (err) { + console.error(`Error writing Continue config file`, err); + return; + } + vscode.window.showInformationMessage(`Updated @Db2-Tables!`) + }) + }) + + } else { + continueAPI?.registerCustomContextProvider(provider); + listDb2TableContextProvider = true; + } } } \ No newline at end of file diff --git a/src/views/jobManager/jobManagerView.ts b/src/views/jobManager/jobManagerView.ts index e967a3a5..71e7caf8 100644 --- a/src/views/jobManager/jobManagerView.ts +++ b/src/views/jobManager/jobManagerView.ts @@ -12,6 +12,7 @@ import { SelfCodesQuickPickItem } from "./selfCodes/selfCodesBrowser"; import { updateStatusBar } from "./statusBar"; import { setCancelButtonVisibility } from "../results"; import { JDBCOptions } from "@ibm/mapepire-js/dist/src/types"; +import { registerDb2iTablesProvider } from "../../aiProviders/continue/listTablesContextProvider"; const selectJobCommand = `vscode-db2i.jobManager.selectJob`; const activeColor = new vscode.ThemeColor(`minimapGutter.addedBackground`); @@ -124,6 +125,9 @@ export class JobManagerView implements TreeDataProvider { try { await selected.job.connect(); + + // re register tables provider with potential new Schema + await registerDb2iTablesProvider(); } catch (e) { window.showErrorMessage(`Failed to start new job with updated properties.`); } From 5beacad72b21e1758d215821bf8c59d035c0a13e Mon Sep 17 00:00:00 2001 From: Adam Shedivy Date: Fri, 20 Dec 2024 12:24:13 -0600 Subject: [PATCH 06/17] just update access info to "save" config --- .../continue/listTablesContextProvider.ts | 21 ++++++------------- 1 file changed, 6 insertions(+), 15 deletions(-) diff --git a/src/aiProviders/continue/listTablesContextProvider.ts b/src/aiProviders/continue/listTablesContextProvider.ts index 9e4a4d84..b196273c 100644 --- a/src/aiProviders/continue/listTablesContextProvider.ts +++ b/src/aiProviders/continue/listTablesContextProvider.ts @@ -131,23 +131,14 @@ export async function registerDb2iTablesProvider() { // HACK: re register context provider work around // save continue config file to trigger a config reload to update list tables provider const configFile = path.join(os.homedir(), `.continue`, `config.json`); - - fs.readFile(configFile, `utf-8`, (err, data) => { + const now = new Date(); + fs.utimes(configFile, now, now, (err) => { if (err) { - console.error('Error reading Continue config file: ', err); + console.error('Error saving Continue config file:', err); + return; } - - const updatedData = data + ``; - - fs.writeFile(configFile, updatedData, `utf-8`, (err) => { - if (err) { - console.error(`Error writing Continue config file`, err); - return; - } - vscode.window.showInformationMessage(`Updated @Db2-Tables!`) - }) - }) - + vscode.window.showInformationMessage('Updated @Db2-Tables!'); + }); } else { continueAPI?.registerCustomContextProvider(provider); listDb2TableContextProvider = true; From 84413821d16b7bce5913c54ae3464c794a3af62e Mon Sep 17 00:00:00 2001 From: Adam Shedivy Date: Fri, 20 Dec 2024 12:27:42 -0600 Subject: [PATCH 07/17] format code --- .../continue/listTablesContextProvider.ts | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/src/aiProviders/continue/listTablesContextProvider.ts b/src/aiProviders/continue/listTablesContextProvider.ts index b196273c..41559cbb 100644 --- a/src/aiProviders/continue/listTablesContextProvider.ts +++ b/src/aiProviders/continue/listTablesContextProvider.ts @@ -1,15 +1,13 @@ -import * as vscode from "vscode"; import { ContextItem, ContextProviderDescription, ContextProviderExtras, ContextSubmenuItem, IContextProvider, LoadSubmenuItemsArgs } from "@continuedev/core"; -import { JobInfo } from "../../connection/manager"; +import * as fs from 'fs'; +import * as os from 'os'; +import * as path from 'path'; +import * as vscode from "vscode"; import { JobManager } from "../../config"; -import { isContinueActive } from "./continueContextProvider"; -import { findPossibleTables } from "../context"; -import Statement from "../../database/statement"; +import { JobInfo } from "../../connection/manager"; import Schemas from "../../database/schemas"; import Table from "../../database/table"; -import * as fs from 'fs'; -import * as path from 'path'; -import * as os from 'os'; +import { findPossibleTables } from "../context"; const listDb2Table: ContextProviderDescription = { title: "list Db2i Tables", @@ -113,7 +111,7 @@ class emptyContextProvider implements IContextProvider { async loadSubmenuItems(args: LoadSubmenuItemsArgs): Promise { return []; } - + } export async function registerDb2iTablesProvider() { @@ -124,7 +122,7 @@ export async function registerDb2iTablesProvider() { if (!continueEx.isActive) { await continueEx.activate(); } - + const continueAPI = continueEx?.exports; if (listDb2TableContextProvider) { From 54fe43b80da7ef39181984979e5c4eba52e2ca3d Mon Sep 17 00:00:00 2001 From: Adam Shedivy Date: Fri, 20 Dec 2024 12:28:05 -0600 Subject: [PATCH 08/17] remove empty context provider --- .../continue/listTablesContextProvider.ts | 18 ------------------ 1 file changed, 18 deletions(-) diff --git a/src/aiProviders/continue/listTablesContextProvider.ts b/src/aiProviders/continue/listTablesContextProvider.ts index 41559cbb..9d6ab22e 100644 --- a/src/aiProviders/continue/listTablesContextProvider.ts +++ b/src/aiProviders/continue/listTablesContextProvider.ts @@ -96,24 +96,6 @@ class ListDb2iTables implements IContextProvider { } } -class emptyContextProvider implements IContextProvider { - get description(): ContextProviderDescription { - return { - title: "", - displayTitle: "", - description: "", - type: "normal" - }; - } - async getContextItems(query: string, extras: ContextProviderExtras): Promise { - return []; - } - async loadSubmenuItems(args: LoadSubmenuItemsArgs): Promise { - return []; - } - -} - export async function registerDb2iTablesProvider() { const provider = new ListDb2iTables(); const continueID = `Continue.continue`; From fc0543553c371d25e086faaf344f3f40121ece7b Mon Sep 17 00:00:00 2001 From: Adam Shedivy Date: Fri, 10 Jan 2025 14:51:30 -0600 Subject: [PATCH 09/17] cleanup list tables provider --- src/aiProviders/context.ts | 20 +++- .../continue/continueContextProvider.ts | 13 +-- .../continue/listTablesContextProvider.ts | 102 ++++++++++-------- src/extension.ts | 2 +- src/views/jobManager/jobManagerView.ts | 5 +- 5 files changed, 83 insertions(+), 59 deletions(-) diff --git a/src/aiProviders/context.ts b/src/aiProviders/context.ts index bd5d9907..cff091d0 100644 --- a/src/aiProviders/context.ts +++ b/src/aiProviders/context.ts @@ -1,6 +1,7 @@ import { JobManager } from "../config"; import * as vscode from "vscode"; import Statement from "../database/statement"; +import { ContextItem } from "@continuedev/core"; export function canTalkToDb() { return JobManager.getSelection() !== undefined; @@ -99,7 +100,7 @@ export async function findPossibleTables(stream: vscode.ChatResponseStream, sche * * Tables with names starting with 'SYS' are skipped. */ -export function refsToMarkdown(refs: TableRefs) { +export function refsToMarkdown(refs: TableRefs): MarkdownRef[] { const condensedResult = Object.keys(refs).length > 5; let markdownRefs: MarkdownRef[] = []; @@ -122,6 +123,23 @@ export function refsToMarkdown(refs: TableRefs) { return markdownRefs; } +export function createContinueContextItems(refs: MarkdownRef[]) { + const contextItems: ContextItem[] = []; + const job = JobManager.getSelection(); + for (const tableRef of refs) { + let prompt = `Table: ${tableRef.TABLE_NAME} (Schema: ${tableRef.SCHMEA}) Column Information:\n`; + prompt += `Format: column_name (column_text) type(length:precision) is_identity is_nullable\n` + prompt += `${tableRef.COLUMN_INFO}`; + contextItems.push({ + name: `${job.name}-${tableRef.SCHMEA}-${tableRef.TABLE_NAME}`, + description: `Column information for ${tableRef.TABLE_NAME}`, + content: prompt, + }); + } + + return contextItems; +} + export async function getSystemStatus(): Promise { const sqlStatment = `SELECT * FROM TABLE(QSYS2.SYSTEM_STATUS(RESET_STATISTICS=>'YES',DETAILED_INFO=>'ALL')) X`; const result = await JobManager.runSQL(sqlStatment, undefined); diff --git a/src/aiProviders/continue/continueContextProvider.ts b/src/aiProviders/continue/continueContextProvider.ts index c4f80500..0e958b26 100644 --- a/src/aiProviders/continue/continueContextProvider.ts +++ b/src/aiProviders/continue/continueContextProvider.ts @@ -2,7 +2,7 @@ import * as vscode from "vscode"; import { JobManager } from "../../config"; import { JobInfo } from "../../connection/manager"; import { SelfCodeNode } from "../../views/jobManager/selfCodes/nodes"; -import { canTalkToDb, findPossibleTables, refsToMarkdown } from "../context"; +import { canTalkToDb, createContinueContextItems, findPossibleTables, refsToMarkdown } from "../context"; import { ContextItem, ContextProviderDescription, @@ -146,16 +146,7 @@ export class db2ContextProvider implements IContextProvider { ); const markdownRefs = refsToMarkdown(tableRefs); - for (const tableRef of markdownRefs) { - let prompt = `Table: ${tableRef.TABLE_NAME} (Schema: ${tableRef.SCHMEA}) Column Information:\n`; - prompt += `Format: column_name (column_text) type(length:precision) is_identity is_nullable\n` - prompt += `${tableRef.COLUMN_INFO}`; - contextItems.push({ - name: `${job.name}-${tableRef.SCHMEA}-${tableRef.TABLE_NAME}`, - description: `Column information for ${tableRef.TABLE_NAME}`, - content: prompt, - }); - } + contextItems.push(...createContinueContextItems(markdownRefs)); return contextItems; } diff --git a/src/aiProviders/continue/listTablesContextProvider.ts b/src/aiProviders/continue/listTablesContextProvider.ts index 9d6ab22e..e660e421 100644 --- a/src/aiProviders/continue/listTablesContextProvider.ts +++ b/src/aiProviders/continue/listTablesContextProvider.ts @@ -1,38 +1,47 @@ -import { ContextItem, ContextProviderDescription, ContextProviderExtras, ContextSubmenuItem, IContextProvider, LoadSubmenuItemsArgs } from "@continuedev/core"; -import * as fs from 'fs'; -import * as os from 'os'; -import * as path from 'path'; +import { + ContextItem, + ContextProviderDescription, + ContextProviderExtras, + ContextSubmenuItem, + IContextProvider, + LoadSubmenuItemsArgs, +} from "@continuedev/core"; +import * as fs from "fs"; +import * as os from "os"; +import * as path from "path"; import * as vscode from "vscode"; -import { JobManager } from "../../config"; -import { JobInfo } from "../../connection/manager"; import Schemas from "../../database/schemas"; import Table from "../../database/table"; -import { findPossibleTables } from "../context"; +import { + createContinueContextItems, + findPossibleTables, + refsToMarkdown, +} from "../context"; const listDb2Table: ContextProviderDescription = { title: "list Db2i Tables", displayTitle: "Db2i-tables", description: "Add Db2i Table info to Context", - type: "submenu" -} + type: "submenu", +}; -export let listDb2TableContextProvider: Boolean = false; +let provider: ListDb2iTables = undefined; class ListDb2iTables implements IContextProvider { + private schema: string; + + constructor(schema: string) { + this.schema = schema; + } + get description(): ContextProviderDescription { return listDb2Table; } - getCurrentJob(): JobInfo { - const currentJob: JobInfo = JobManager.getSelection(); - return currentJob; + setCurrentSchema(schema: string) { + this.schema = schema; } - private getDefaultSchema = (): string => { - const currentJob: JobInfo = this.getCurrentJob(); - return currentJob?.job.options.libraries[0] || "QGPL"; - }; - async getColumnInfoForAllTables(schema: string) { const items: TableColumn[] = await Table.getItems(schema); @@ -48,42 +57,47 @@ class ListDb2iTables implements IContextProvider { query: string, extras: ContextProviderExtras ): Promise { - let contextitems: ContextItem[] = []; - const schema = this.getDefaultSchema(); - if (query.toUpperCase() === schema.toUpperCase()) { - const tableInfo = await this.getColumnInfoForAllTables(schema); - contextitems.push({ - name: `Info for all tables in ${schema}`, - content: `Db2 for i table Assistant: The following table and column information is from the ${query} schema. Utilize the provided schema and table metadata to assist the user:\n${JSON.stringify(tableInfo)}`, + let contextItems: ContextItem[] = []; + if (query.toUpperCase() === this.schema.toUpperCase()) { + const tableInfo = await this.getColumnInfoForAllTables(this.schema); + contextItems.push({ + name: `Info for all tables in ${this.schema}`, + content: `Db2 for i table Assistant: The following table and column information is from the ${query} schema. Utilize the provided schema and table metadata to assist the user:\n${JSON.stringify( + tableInfo + )}`, description: "table metadata", }); } else { const tableInfo = await findPossibleTables( null, - schema, + this.schema, query.split(` `) ); - contextitems.push({ - name: `${query}`, - content: `Db2 for i table Assistant: The following information is based on the ${query} table within the ${schema} schema. Utilize the provided schema and table metadata to assist the user:\n${JSON.stringify(tableInfo)}`, - description: "table metadata", + const markdownRefs = refsToMarkdown(tableInfo); + + // add additional context for working with Db2 for i tables + contextItems.push({ + name: `Instructions`, + content: `Db2 for i table Assistant: The following information is based on the ${query} table within the ${this.schema} schema. Utilize the provided schema and table metadata to assist the user. Only use valid Db2 for i SQL syntax and conventions. If input is unclear ask user to clarify`, + description: "instructions for working with Db2 for i tables", }); + + contextItems.push(...createContinueContextItems(markdownRefs)); } - return contextitems; + return contextItems; } async loadSubmenuItems( args: LoadSubmenuItemsArgs ): Promise { - const schema = this.getDefaultSchema(); - const tables: BasicSQLObject[] = await Schemas.getObjects(schema, [ + const tables: BasicSQLObject[] = await Schemas.getObjects(this.schema, [ `tables`, ]); const schemaSubmenuItem: ContextSubmenuItem = { - id: schema, - title: schema, - description: `All table info in schema: ${schema}`, + id: this.schema, + title: this.schema, + description: `All table info in schema: ${this.schema}`, }; const tableSubmenuItems: ContextSubmenuItem[] = tables.map((table) => ({ @@ -96,8 +110,7 @@ class ListDb2iTables implements IContextProvider { } } -export async function registerDb2iTablesProvider() { - const provider = new ListDb2iTables(); +export async function registerDb2iTablesProvider(schema: string) { const continueID = `Continue.continue`; const continueEx = vscode.extensions.getExtension(continueID); if (continueEx) { @@ -105,23 +118,22 @@ export async function registerDb2iTablesProvider() { await continueEx.activate(); } - const continueAPI = continueEx?.exports; - if (listDb2TableContextProvider) { - + if (provider) { + provider.setCurrentSchema(schema); // HACK: re register context provider work around // save continue config file to trigger a config reload to update list tables provider const configFile = path.join(os.homedir(), `.continue`, `config.json`); const now = new Date(); fs.utimes(configFile, now, now, (err) => { if (err) { - console.error('Error saving Continue config file:', err); + console.error("Error saving Continue config file:", err); return; } - vscode.window.showInformationMessage('Updated @Db2-Tables!'); }); } else { + const continueAPI = continueEx?.exports; + provider = new ListDb2iTables(schema); continueAPI?.registerCustomContextProvider(provider); - listDb2TableContextProvider = true; } } -} \ No newline at end of file +} diff --git a/src/extension.ts b/src/extension.ts index 55ae49c5..13e5f5f1 100644 --- a/src/extension.ts +++ b/src/extension.ts @@ -102,7 +102,7 @@ export function activate(context: vscode.ExtensionContext): Db2i { exampleBrowser.refresh(); selfCodesView.setRefreshEnabled(Configuration.get(`jobSelfViewAutoRefresh`) || false); // register list tables - registerDb2iTablesProvider(); + registerDb2iTablesProvider(JobManager.getSelection().job.options.libraries[0]); if (devMode && runTests) { runTests(); } diff --git a/src/views/jobManager/jobManagerView.ts b/src/views/jobManager/jobManagerView.ts index ae43f051..4f85d359 100644 --- a/src/views/jobManager/jobManagerView.ts +++ b/src/views/jobManager/jobManagerView.ts @@ -128,7 +128,8 @@ export class JobManagerView implements TreeDataProvider { await selected.job.connect(); // re register tables provider with potential new Schema - await registerDb2iTablesProvider(); + const schema = selected.job.options.libraries[0]; + await registerDb2iTablesProvider(schema); } catch (e) { window.showErrorMessage(`Failed to start new job with updated properties.`); } @@ -280,6 +281,8 @@ export class JobManagerView implements TreeDataProvider { vscode.commands.registerCommand(selectJobCommand, async (selectedName: string) => { if (selectedName) { await JobManager.setSelection(selectedName); + const schema = JobManager.getSelection().job.options.libraries[0]; + await registerDb2iTablesProvider(schema); this.refresh(); } }), From b8ab3b8369d777fbc31b989b40c3160731b10ee4 Mon Sep 17 00:00:00 2001 From: Adam Shedivy Date: Tue, 14 Jan 2025 10:06:15 -0600 Subject: [PATCH 10/17] use binding parameter --- src/aiProviders/continue/listTablesContextProvider.ts | 5 +---- src/database/table.ts | 8 ++++---- 2 files changed, 5 insertions(+), 8 deletions(-) diff --git a/src/aiProviders/continue/listTablesContextProvider.ts b/src/aiProviders/continue/listTablesContextProvider.ts index e660e421..b98cabd8 100644 --- a/src/aiProviders/continue/listTablesContextProvider.ts +++ b/src/aiProviders/continue/listTablesContextProvider.ts @@ -28,9 +28,7 @@ const listDb2Table: ContextProviderDescription = { let provider: ListDb2iTables = undefined; class ListDb2iTables implements IContextProvider { - private schema: string; - - constructor(schema: string) { + constructor(private schema: string) { this.schema = schema; } @@ -120,7 +118,6 @@ export async function registerDb2iTablesProvider(schema: string) { if (provider) { provider.setCurrentSchema(schema); - // HACK: re register context provider work around // save continue config file to trigger a config reload to update list tables provider const configFile = path.join(os.homedir(), `.continue`, `config.json`); const now = new Date(); diff --git a/src/database/table.ts b/src/database/table.ts index 91d3cf08..27972458 100644 --- a/src/database/table.ts +++ b/src/database/table.ts @@ -5,11 +5,11 @@ import { getInstance } from "../base"; export default class Table { /** * @param {string} schema Not user input - * @param {string} name Not user input + * @param {string} table Not user input * @returns {Promise} */ - static async getItems(schema: string, name?: string): Promise { - const params = name ? [schema, name] : [schema]; + static async getItems(schema: string, table?: string): Promise { + const params = table ? [schema, table] : [schema]; const sql = [ `SELECT `, ` column.TABLE_SCHEMA,`, @@ -33,7 +33,7 @@ export default class Table { ` column.column_name = key.column_name`, `WHERE column.TABLE_SCHEMA = ?`, ...[ - name ? `AND column.TABLE_NAME = ${name}` : ``, + table ? `AND column.TABLE_NAME = ?` : ``, ], `ORDER BY column.ORDINAL_POSITION`, ].join(` `); From c7d4a9f22937b87cc57afd3c45e186faa7ae1149 Mon Sep 17 00:00:00 2001 From: Adam Shedivy Date: Tue, 14 Jan 2025 10:46:59 -0600 Subject: [PATCH 11/17] move register tables provider to refresh function --- src/views/jobManager/jobManagerView.ts | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/src/views/jobManager/jobManagerView.ts b/src/views/jobManager/jobManagerView.ts index 4f85d359..a8afdd5e 100644 --- a/src/views/jobManager/jobManagerView.ts +++ b/src/views/jobManager/jobManagerView.ts @@ -126,10 +126,6 @@ export class JobManagerView implements TreeDataProvider { try { await selected.job.connect(); - - // re register tables provider with potential new Schema - const schema = selected.job.options.libraries[0]; - await registerDb2iTablesProvider(schema); } catch (e) { window.showErrorMessage(`Failed to start new job with updated properties.`); } @@ -281,8 +277,6 @@ export class JobManagerView implements TreeDataProvider { vscode.commands.registerCommand(selectJobCommand, async (selectedName: string) => { if (selectedName) { await JobManager.setSelection(selectedName); - const schema = JobManager.getSelection().job.options.libraries[0]; - await registerDb2iTablesProvider(schema); this.refresh(); } }), @@ -310,6 +304,9 @@ export class JobManagerView implements TreeDataProvider { updateStatusBar(); const selectedJob = JobManager.getSelection(); + + // re-register db2i tables context provider with current schema + registerDb2iTablesProvider(selectedJob.job.options.libraries[0]); setCancelButtonVisibility(selectedJob && selectedJob.job.getStatus() === "busy"); sqlLanguageStatus.setState(selectedJob !== undefined); From fc83050cc74898c6d26df5cbd69ba3949c5939d5 Mon Sep 17 00:00:00 2001 From: Adam Shedivy Date: Tue, 14 Jan 2025 10:56:09 -0600 Subject: [PATCH 12/17] check if schema has changed, then update provider --- src/aiProviders/continue/listTablesContextProvider.ts | 6 +++++- src/views/jobManager/jobManagerView.ts | 7 +++++-- 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/src/aiProviders/continue/listTablesContextProvider.ts b/src/aiProviders/continue/listTablesContextProvider.ts index b98cabd8..fff02842 100644 --- a/src/aiProviders/continue/listTablesContextProvider.ts +++ b/src/aiProviders/continue/listTablesContextProvider.ts @@ -25,7 +25,7 @@ const listDb2Table: ContextProviderDescription = { type: "submenu", }; -let provider: ListDb2iTables = undefined; +export let provider: ListDb2iTables = undefined; class ListDb2iTables implements IContextProvider { constructor(private schema: string) { @@ -40,6 +40,10 @@ class ListDb2iTables implements IContextProvider { this.schema = schema; } + getCurrentSchema() { + return this.schema; + } + async getColumnInfoForAllTables(schema: string) { const items: TableColumn[] = await Table.getItems(schema); diff --git a/src/views/jobManager/jobManagerView.ts b/src/views/jobManager/jobManagerView.ts index a8afdd5e..b203bae5 100644 --- a/src/views/jobManager/jobManagerView.ts +++ b/src/views/jobManager/jobManagerView.ts @@ -12,7 +12,7 @@ import { SelfCodesQuickPickItem } from "./selfCodes/selfCodesBrowser"; import { updateStatusBar } from "./statusBar"; import { setCancelButtonVisibility } from "../results"; import { JDBCOptions } from "@ibm/mapepire-js/dist/src/types"; -import { registerDb2iTablesProvider } from "../../aiProviders/continue/listTablesContextProvider"; +import { provider, registerDb2iTablesProvider } from "../../aiProviders/continue/listTablesContextProvider"; import { sqlLanguageStatus } from "../../language/providers"; const selectJobCommand = `vscode-db2i.jobManager.selectJob`; @@ -304,9 +304,12 @@ export class JobManagerView implements TreeDataProvider { updateStatusBar(); const selectedJob = JobManager.getSelection(); + const selectedSchema = selectedJob.job.options.libraries[0]; // re-register db2i tables context provider with current schema - registerDb2iTablesProvider(selectedJob.job.options.libraries[0]); + if (provider && provider.getCurrentSchema().toLowerCase() !== selectedSchema.toLowerCase()) { + registerDb2iTablesProvider(selectedJob.job.options.libraries[0]); + } setCancelButtonVisibility(selectedJob && selectedJob.job.getStatus() === "busy"); sqlLanguageStatus.setState(selectedJob !== undefined); From 14846f7046a41c4706f076af90d878f38fdf7acf Mon Sep 17 00:00:00 2001 From: Adam Shedivy Date: Tue, 14 Jan 2025 10:57:13 -0600 Subject: [PATCH 13/17] fix typo --- src/views/jobManager/jobManagerView.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/views/jobManager/jobManagerView.ts b/src/views/jobManager/jobManagerView.ts index b203bae5..fdcbc504 100644 --- a/src/views/jobManager/jobManagerView.ts +++ b/src/views/jobManager/jobManagerView.ts @@ -308,7 +308,7 @@ export class JobManagerView implements TreeDataProvider { // re-register db2i tables context provider with current schema if (provider && provider.getCurrentSchema().toLowerCase() !== selectedSchema.toLowerCase()) { - registerDb2iTablesProvider(selectedJob.job.options.libraries[0]); + registerDb2iTablesProvider(selectedSchema); } setCancelButtonVisibility(selectedJob && selectedJob.job.getStatus() === "busy"); From 5ba9b374f075c4a5852281ca9a05acb59b929329 Mon Sep 17 00:00:00 2001 From: Adam Shedivy Date: Tue, 14 Jan 2025 12:06:49 -0600 Subject: [PATCH 14/17] improve checks for current job and current schema --- .../continue/listTablesContextProvider.ts | 5 ++++- src/extension.ts | 4 +++- src/views/jobManager/jobManagerView.ts | 21 +++++++++++++++---- 3 files changed, 24 insertions(+), 6 deletions(-) diff --git a/src/aiProviders/continue/listTablesContextProvider.ts b/src/aiProviders/continue/listTablesContextProvider.ts index fff02842..47969a14 100644 --- a/src/aiProviders/continue/listTablesContextProvider.ts +++ b/src/aiProviders/continue/listTablesContextProvider.ts @@ -112,7 +112,10 @@ class ListDb2iTables implements IContextProvider { } } -export async function registerDb2iTablesProvider(schema: string) { +export async function registerDb2iTablesProvider(schema?: string) { + if (!schema) { + return; + } const continueID = `Continue.continue`; const continueEx = vscode.extensions.getExtension(continueID); if (continueEx) { diff --git a/src/extension.ts b/src/extension.ts index 13e5f5f1..219b0a39 100644 --- a/src/extension.ts +++ b/src/extension.ts @@ -102,7 +102,9 @@ export function activate(context: vscode.ExtensionContext): Db2i { exampleBrowser.refresh(); selfCodesView.setRefreshEnabled(Configuration.get(`jobSelfViewAutoRefresh`) || false); // register list tables - registerDb2iTablesProvider(JobManager.getSelection().job.options.libraries[0]); + const currentJob = JobManager.getSelection(); + const currentSchema = currentJob?.job.options.libraries[0]; + registerDb2iTablesProvider(currentSchema); if (devMode && runTests) { runTests(); } diff --git a/src/views/jobManager/jobManagerView.ts b/src/views/jobManager/jobManagerView.ts index fdcbc504..e0c97e3c 100644 --- a/src/views/jobManager/jobManagerView.ts +++ b/src/views/jobManager/jobManagerView.ts @@ -305,15 +305,28 @@ export class JobManagerView implements TreeDataProvider { const selectedJob = JobManager.getSelection(); const selectedSchema = selectedJob.job.options.libraries[0]; - + // re-register db2i tables context provider with current schema - if (provider && provider.getCurrentSchema().toLowerCase() !== selectedSchema.toLowerCase()) { + if ( + provider && + selectedJob !== undefined && + provider.getCurrentSchema() && + selectedSchema && + provider.getCurrentSchema().trim().toLowerCase() !== + selectedSchema.trim().toLowerCase() + ) { registerDb2iTablesProvider(selectedSchema); } - setCancelButtonVisibility(selectedJob && selectedJob.job.getStatus() === "busy"); + setCancelButtonVisibility( + selectedJob && selectedJob.job.getStatus() === "busy" + ); sqlLanguageStatus.setState(selectedJob !== undefined); - commands.executeCommand(`setContext`, `vscode-db2i:jobManager.hasJob`, selectedJob !== undefined); + commands.executeCommand( + `setContext`, + `vscode-db2i:jobManager.hasJob`, + selectedJob !== undefined + ); } getTreeItem(element: vscode.TreeItem) { From 9ff1e7303ccc761ff8bd0ee844345dacd1a182b7 Mon Sep 17 00:00:00 2001 From: Adam Shedivy Date: Tue, 14 Jan 2025 12:25:57 -0600 Subject: [PATCH 15/17] add optional chaining operator to selected job --- src/views/jobManager/jobManagerView.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/views/jobManager/jobManagerView.ts b/src/views/jobManager/jobManagerView.ts index e0c97e3c..9eaf046b 100644 --- a/src/views/jobManager/jobManagerView.ts +++ b/src/views/jobManager/jobManagerView.ts @@ -304,7 +304,7 @@ export class JobManagerView implements TreeDataProvider { updateStatusBar(); const selectedJob = JobManager.getSelection(); - const selectedSchema = selectedJob.job.options.libraries[0]; + const selectedSchema = selectedJob?.job.options.libraries[0]; // re-register db2i tables context provider with current schema if ( From b0aa3c2c2502dbfc106eae105811d295180f7e67 Mon Sep 17 00:00:00 2001 From: Adam Shedivy Date: Tue, 14 Jan 2025 12:33:22 -0600 Subject: [PATCH 16/17] clean up logic --- src/views/jobManager/jobManagerView.ts | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/src/views/jobManager/jobManagerView.ts b/src/views/jobManager/jobManagerView.ts index 9eaf046b..52b66aec 100644 --- a/src/views/jobManager/jobManagerView.ts +++ b/src/views/jobManager/jobManagerView.ts @@ -304,16 +304,15 @@ export class JobManagerView implements TreeDataProvider { updateStatusBar(); const selectedJob = JobManager.getSelection(); - const selectedSchema = selectedJob?.job.options.libraries[0]; - + // re-register db2i tables context provider with current schema + const selectedSchema = selectedJob?.job.options.libraries[0]?.trim().toLowerCase(); + const currentSchema = provider?.getCurrentSchema().trim().toLowerCase(); if ( provider && - selectedJob !== undefined && - provider.getCurrentSchema() && + selectedJob && selectedSchema && - provider.getCurrentSchema().trim().toLowerCase() !== - selectedSchema.trim().toLowerCase() + currentSchema !== selectedSchema ) { registerDb2iTablesProvider(selectedSchema); } From e03b84e1e9bdf53820544313124f18bee6970805 Mon Sep 17 00:00:00 2001 From: Adam Shedivy Date: Wed, 15 Jan 2025 13:15:58 -0600 Subject: [PATCH 17/17] use same case in comparison --- src/views/jobManager/jobManagerView.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/views/jobManager/jobManagerView.ts b/src/views/jobManager/jobManagerView.ts index 52b66aec..c8cbbb68 100644 --- a/src/views/jobManager/jobManagerView.ts +++ b/src/views/jobManager/jobManagerView.ts @@ -306,13 +306,13 @@ export class JobManagerView implements TreeDataProvider { const selectedJob = JobManager.getSelection(); // re-register db2i tables context provider with current schema - const selectedSchema = selectedJob?.job.options.libraries[0]?.trim().toLowerCase(); - const currentSchema = provider?.getCurrentSchema().trim().toLowerCase(); + const selectedSchema = selectedJob?.job.options.libraries[0]; + const currentSchema = provider?.getCurrentSchema(); if ( provider && selectedJob && selectedSchema && - currentSchema !== selectedSchema + currentSchema.toLowerCase() !== selectedSchema.toLowerCase() ) { registerDb2iTablesProvider(selectedSchema); }