Skip to content

Commit 52a0d25

Browse files
authored
Merge branch 'main' into fix/tersedata
2 parents f2a0483 + 6fc6aaf commit 52a0d25

File tree

22 files changed

+530
-188
lines changed

22 files changed

+530
-188
lines changed

.github/workflows/webpack_ci.yaml

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -29,11 +29,24 @@ jobs:
2929
npm install -g vsce
3030
vsce package
3131
32-
- name: Copy dist artifacts to staging directory
33-
run: mkdir staging && cp ./*.vsix staging
32+
- name: get .vsix name
33+
run: |
34+
echo "vsix_name=$(echo *.vsix)" >> $GITHUB_ENV
35+
cat $GITHUB_ENV
3436
3537
- name: Upload dist artifacts
3638
uses: actions/upload-artifact@v3
3739
with:
38-
name: Package
39-
path: staging
40+
name: test_vsix
41+
path: ${{env.vsix_name}}
42+
43+
- name: Post comment
44+
uses: actions/github-script@v5
45+
with:
46+
script: |
47+
github.rest.issues.createComment({
48+
issue_number: context.issue.number,
49+
owner: context.repo.owner,
50+
repo: context.repo.repo,
51+
body: '👋 A new build is available for this PR based on ${{ github.event.pull_request.head.sha }}.\n * [Download here.](https://github.com/halcyon-tech/vscode-db2i/actions/runs/${{ github.run_id }})\n'
52+
})

global.d.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ interface BasicSQLObject {
3939
type: string;
4040
schema: string;
4141
name: string;
42+
specificName: string;
4243
text: string;
4344
system: {
4445
schema: string;

package.json

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -157,10 +157,10 @@
157157
"icon": "$(refresh)"
158158
},
159159
{
160-
"command": "vscode-db2i.addSchemaToSchemaBrowser",
161-
"title": "Add Schema to Schema Browser",
160+
"command": "vscode-db2i.manageSchemaBrowserList",
161+
"title": "Manage Schema Browser List",
162162
"category": "Db2 for i",
163-
"icon": "$(add)"
163+
"icon": "$(list-selection)"
164164
},
165165
{
166166
"command": "vscode-db2i.removeSchemaFromSchemaBrowser",
@@ -388,9 +388,9 @@
388388
],
389389
"view/title": [
390390
{
391-
"command": "vscode-db2i.addSchemaToSchemaBrowser",
391+
"command": "vscode-db2i.manageSchemaBrowserList",
392392
"group": "navigation",
393-
"when": "view == schemaBrowser"
393+
"when": "view == schemaBrowser && vscode-db2i:manageSchemaBrowserEnabled"
394394
},
395395
{
396396
"command": "vscode-db2i.refreshSchemaBrowser",
@@ -552,7 +552,7 @@
552552
"webpack-dev": "webpack --mode development --watch"
553553
},
554554
"devDependencies": {
555-
"@halcyontech/vscode-ibmi-types": "^1.8.0",
555+
"@halcyontech/vscode-ibmi-types": "^2.0.0",
556556
"@types/glob": "^7.1.3",
557557
"@types/node": "14.x",
558558
"@types/vscode": "^1.70.0",

src/connection/manager.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,7 @@ export class SQLJobManager {
8989

9090
return (this.selectedJob >= 0);
9191
}
92+
9293
/**
9394
* Runs SQL
9495
* @param query the SQL query
@@ -98,6 +99,7 @@ export class SQLJobManager {
9899
* @returns
99100
*/
100101
async runSQL<T>(query: string, parameters: any[] = [], isTerseResults: boolean = false): Promise<T[]> {
102+
101103
// 2147483647 is NOT arbitrary. On the server side, this is processed as a Java
102104
// int. This is the largest number available without overflow (Integer.MAX_VALUE)
103105
const rowsToFetch = 2147483647;

src/connection/serverComponent.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ const octokit = new Octokit();
1414

1515
// During development, you can set the SERVER_VERSION in .vscode/launch.json
1616
// Otherwise, fall back to the working version
17-
const SERVER_VERSION = process.env[`SERVER_VERSION`] || `v1.1.1`;
17+
const SERVER_VERSION = process.env[`SERVER_VERSION`] || `v1.2.0`;
1818

1919
const ExecutablePathDir = `$HOME/.vscode/`;
2020

@@ -56,7 +56,7 @@ export class ServerComponent {
5656
const path = this.getComponentPath();
5757

5858
if (path) {
59-
return `/QOpenSys/QIBM/ProdData/JavaVM/jdk80/64bit/bin/java -jar ${path}`
59+
return `/QOpenSys/QIBM/ProdData/JavaVM/jdk80/64bit/bin/java -Dos400.stdio.convert=N -jar ${path}`
6060
}
6161
}
6262

src/connection/sqlJob.ts

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,8 @@ const TransactionCountQuery = [
2828
` (local_record_changes_pending = 'YES' or local_object_changes_pending = 'YES')`,
2929
].join(`\n`);
3030

31+
const DB2I_VERSION = (process.env[`DB2I_VERSION`] || `<version unknown>`) + ((process.env.DEV) ? ``:`-dev`);
32+
3133
export class SQLJob {
3234

3335
private static uniqueIdCounter: number = 0;
@@ -54,7 +56,8 @@ export class SQLJob {
5456
const instance = getInstance();
5557
const connection = instance.getConnection();
5658
return new Promise((resolve, reject) => {
57-
connection.client.connection.exec(ServerComponent.getInitCommand() + ` && exit`, {}, (err: any, stream: any) => {
59+
// Setting QIBM_JAVA_STDIO_CONVERT and QIBM_PASE_DESCRIPTOR_STDIO to make sure all PASE and Java converters are off
60+
connection.client.connection.exec(`QIBM_JAVA_STDIO_CONVERT=N QIBM_PASE_DESCRIPTOR_STDIO=B exec `+ServerComponent.getInitCommand(), {}, (err: any, stream: any, options: {encoding: `binary`}) => {
5861
if (err)
5962
reject(err);
6063
let outString = ``;
@@ -114,6 +117,8 @@ export class SQLJob {
114117
const connectionObject = {
115118
id: SQLJob.getNewUniqueId(),
116119
type: `connect`,
120+
technique: (65535 === getInstance().getConnection().qccsid) ? `tcp` : `cli`, //TODO: investigate why QCCSID 65535 breaks CLI and if there is any workaround
121+
application: `vscode-db2i ${DB2I_VERSION}`,
117122
props: props.length > 0 ? props : undefined
118123
}
119124

src/connection/types.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ export interface QueryResult<T> extends ServerResponse {
4343
metadata: QueryMetaData,
4444
is_done: boolean;
4545
has_results: boolean;
46+
update_count: number;
4647
data: T[];
4748
}
4849

src/database/callable.ts

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,23 @@
11

22
import vscode from "vscode"
33
import { JobManager } from "../config";
4-
import Statement from "./statement";
4+
import { QueryOptions } from "../connection/types";
55
const {instance} = vscode.extensions.getExtension(`halcyontechltd.code-for-ibmi`).exports;
66

77
export default class Callable {
88
/**
99
* @param schema Not user input
10-
* @param name Not user input
10+
* @param specificName Not user input
1111
* @returns
1212
*/
13-
static getParms(schema: string, name: string): Promise<SQLParm[]> {
13+
static getParms(schema: string, specificName: string): Promise<SQLParm[]> {
14+
const rowType = `P`; // Parameter
15+
const options : QueryOptions = { parameters : [schema, specificName, rowType] };
1416
return JobManager.runSQL<SQLParm>([
1517
`SELECT * FROM QSYS2.SYSPARMS`,
16-
`WHERE SPECIFIC_SCHEMA = '${schema}' AND SPECIFIC_NAME = (select SPECIFIC_NAME from qsys2.sysroutines where ROUTINE_SCHEMA = '${schema}' and ROUTINE_NAME = '${name}') and ROW_TYPE = 'P'`,
18+
`WHERE SPECIFIC_SCHEMA = ? AND SPECIFIC_NAME = ? and ROW_TYPE = ?`,
1719
`ORDER BY ORDINAL_POSITION`
18-
].join(` `));
20+
].join(` `),
21+
options);
1922
}
2023
}

src/database/schemas.ts

Lines changed: 79 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import { getInstance } from "../base";
44
import Statement from "./statement";
55
import { JobManager } from "../config";
66

7-
type SQLType = "tables"|"views"|"aliases"|"constraints"|"functions"|"variables"|"indexes"|"procedures"|"sequences"|"packages"|"triggers"|"types";
7+
type SQLType = "schemas"|"tables"|"views"|"aliases"|"constraints"|"functions"|"variables"|"indexes"|"procedures"|"sequences"|"packages"|"triggers"|"types";
88
type PageData = {filter?: string, offset?: number, limit?: number};
99

1010
const typeMap = {
@@ -18,114 +18,127 @@ export default class Database {
1818
* @param schema Not user input
1919
*/
2020
static async getObjects(schema: string, type: SQLType, details: PageData = {}): Promise<BasicSQLObject[]> {
21-
let objects;
22-
21+
let query : string;
2322
switch (type) {
23+
case `schemas`:
24+
query = [
25+
`select SCHEMA_NAME as NAME, SCHEMA_TEXT as TEXT, SYSTEM_SCHEMA_NAME as SYS_NAME `,
26+
`from QSYS2.SYSSCHEMAS`,
27+
details.filter ? `where SCHEMA_NAME = '${details.filter}' or SYSTEM_SCHEMA_NAME = '${details.filter}'` : ``,
28+
`order by QSYS2.DELIMIT_NAME(SCHEMA_NAME) asc`
29+
].join(` `);
30+
break;
2431
case `tables`:
2532
case `views`:
2633
case `aliases`:
27-
objects = await JobManager.runSQL([
28-
`select TABLE_NAME as NAME, TABLE_TEXT as TEXT, BASE_TABLE_SCHEMA as BASE_SCHEMA, BASE_TABLE_NAME as BASE_OBJ, SYSTEM_TABLE_NAME as SYS_NAME, SYSTEM_TABLE_SCHEMA as SYS_SCHEMA from QSYS2.SYSTABLES`,
34+
query = [
35+
`select TABLE_NAME as NAME, TABLE_TEXT as TEXT, BASE_TABLE_SCHEMA as BASE_SCHEMA, BASE_TABLE_NAME as BASE_OBJ, SYSTEM_TABLE_NAME as SYS_NAME, SYSTEM_TABLE_SCHEMA as SYS_SCHEMA `,
36+
`from QSYS2.SYSTABLES`,
2937
`where TABLE_SCHEMA = '${schema}' and TABLE_TYPE in (${typeMap[type].map(item => `'${item}'`).join(`, `)}) ${details.filter ? `and TABLE_NAME like '%${details.filter}%'`: ``}`,
30-
`order by TABLE_NAME asc`,
31-
`${details.limit ? `limit ${details.limit}` : ``} ${details.offset ? `offset ${details.offset}` : ``}`
32-
].join(` `));
38+
`order by TABLE_NAME asc`
39+
].join(` `);
3340
break;
3441

3542
case `constraints`:
36-
objects = await JobManager.runSQL([
37-
`select CONSTRAINT_NAME as NAME, CONSTRAINT_TEXT as TEXT, TABLE_SCHEMA as BASE_SCHEMA, TABLE_NAME as BASE_OBJ, SYSTEM_TABLE_NAME as SYS_NAME, SYSTEM_TABLE_SCHEMA as SYS_SCHEMA from QSYS2.SYSCST`,
43+
query = [
44+
`select CONSTRAINT_NAME as NAME, CONSTRAINT_TEXT as TEXT, TABLE_SCHEMA as BASE_SCHEMA, TABLE_NAME as BASE_OBJ, SYSTEM_TABLE_NAME as SYS_NAME, SYSTEM_TABLE_SCHEMA as SYS_SCHEMA `,
45+
`from QSYS2.SYSCST`,
3846
`where CONSTRAINT_SCHEMA = '${schema}' ${details.filter ? `and CONSTRAINT_NAME like '%${details.filter}%'`: ``}`,
39-
`order by CONSTRAINT_NAME asc`,
40-
`${details.limit ? `limit ${details.limit}` : ``} ${details.offset ? `offset ${details.offset}` : ``}`
41-
].join(` `));
47+
`order by CONSTRAINT_NAME asc`
48+
].join(` `);
4249
break;
4350

4451
case `functions`:
45-
objects = await JobManager.runSQL([
46-
`select ROUTINE_NAME as NAME, coalesce(ROUTINE_TEXT, LONG_COMMENT) as TEXT from QSYS2.SYSFUNCS`,
52+
query = [
53+
`select ROUTINE_NAME as NAME, SPECIFIC_NAME as SPECNAME, coalesce(ROUTINE_TEXT, LONG_COMMENT) as TEXT `,
54+
`from QSYS2.SYSFUNCS`,
4755
`where ROUTINE_SCHEMA = '${schema}' ${details.filter ? `and ROUTINE_NAME like '%${details.filter}%'`: ``} and FUNCTION_ORIGIN in ('E','U')`,
48-
`order by ROUTINE_NAME asc`,
49-
`${details.limit ? `limit ${details.limit}` : ``} ${details.offset ? `offset ${details.offset}` : ``}`
50-
].join(` `));
56+
`order by ROUTINE_NAME asc`
57+
].join(` `);
5158
break;
5259

5360
case `variables`:
54-
objects = await JobManager.runSQL([
55-
`select VARIABLE_NAME as NAME, VARIABLE_TEXT as TEXT, SYSTEM_VAR_NAME as SYS_NAME, SYSTEM_VAR_SCHEMA as SYS_SCHEMA from QSYS2.SYSVARIABLES`,
61+
query = [
62+
`select VARIABLE_NAME as NAME, VARIABLE_TEXT as TEXT, SYSTEM_VAR_NAME as SYS_NAME, SYSTEM_VAR_SCHEMA as SYS_SCHEMA `,
63+
`from QSYS2.SYSVARIABLES`,
5664
`where VARIABLE_SCHEMA = '${schema}' ${details.filter ? `and VARIABLE_NAME like '%${details.filter}%'`: ``}`,
57-
`order by VARIABLE_NAME asc`,
58-
`${details.limit ? `limit ${details.limit}` : ``} ${details.offset ? `offset ${details.offset}` : ``}`
59-
].join(` `));
65+
`order by VARIABLE_NAME asc`
66+
].join(` `);
6067
break;
6168

6269
case `indexes`:
63-
objects = await JobManager.runSQL([
64-
`select INDEX_NAME as NAME, INDEX_TEXT as TEXT, TABLE_SCHEMA as BASE_SCHEMA, TABLE_NAME as BASE_OBJ, SYSTEM_INDEX_NAME as SYS_NAME, SYSTEM_INDEX_SCHEMA as SYS_SCHEMA from QSYS2.SYSINDEXES`,
70+
query = [
71+
`select INDEX_NAME as NAME, INDEX_TEXT as TEXT, TABLE_SCHEMA as BASE_SCHEMA, TABLE_NAME as BASE_OBJ, SYSTEM_INDEX_NAME as SYS_NAME, SYSTEM_INDEX_SCHEMA as SYS_SCHEMA `,
72+
`from QSYS2.SYSINDEXES`,
6573
`where INDEX_SCHEMA = '${schema}' ${details.filter ? `and INDEX_NAME like '%${details.filter}%'`: ``}`,
66-
`order by INDEX_NAME asc`,
67-
`${details.limit ? `limit ${details.limit}` : ``} ${details.offset ? `offset ${details.offset}` : ``}`
68-
].join(` `));
74+
`order by INDEX_NAME asc`
75+
].join(` `);
6976
break;
7077

7178
case `procedures`:
72-
objects = await JobManager.runSQL([
73-
`select ROUTINE_NAME as NAME, ROUTINE_TEXT as TEXT from QSYS2.SYSPROCS`,
79+
query = [
80+
`select ROUTINE_NAME as NAME, SPECIFIC_NAME as SPECNAME, ROUTINE_TEXT as TEXT `,
81+
`from QSYS2.SYSPROCS`,
7482
`where ROUTINE_SCHEMA = '${schema}' ${details.filter ? `and ROUTINE_NAME like '%${details.filter}%'`: ``}`,
75-
`order by ROUTINE_NAME asc`,
76-
`${details.limit ? `limit ${details.limit}` : ``} ${details.offset ? `offset ${details.offset}` : ``}`
77-
].join(` `));
83+
`order by ROUTINE_NAME asc`
84+
].join(` `);
7885
break;
7986

8087
case `sequences`:
81-
objects = await JobManager.runSQL([
82-
`select SEQUENCE_NAME as NAME, SEQUENCE_TEXT as TEXT, SYSTEM_SEQ_NAME as SYS_NAME, SYSTEM_SEQ_SCHEMA as SYS_SCHEMA from QSYS2.SYSSEQUENCES`,
88+
query = [
89+
`select SEQUENCE_NAME as NAME, SEQUENCE_TEXT as TEXT, SYSTEM_SEQ_NAME as SYS_NAME, SYSTEM_SEQ_SCHEMA as SYS_SCHEMA `,
90+
`from QSYS2.SYSSEQUENCES`,
8391
`where SEQUENCE_SCHEMA = '${schema}' ${details.filter ? `and SEQUENCE_NAME like '%${details.filter}%'`: ``}`,
84-
`order by SEQUENCE_NAME asc`,
85-
`${details.limit ? `limit ${details.limit}` : ``} ${details.offset ? `offset ${details.offset}` : ``}`
86-
].join(` `));
92+
`order by SEQUENCE_NAME asc`
93+
].join(` `);
8794
break;
8895

8996
case `packages`:
90-
objects = await JobManager.runSQL([
91-
`select PACKAGE_NAME as NAME, PACKAGE_TEXT as TEXT, PROGRAM_SCHEMA as BASE_SCHEMA, PROGRAM_NAME as BASE_OBJ from QSYS2.SQLPACKAGE`,
97+
query = [
98+
`select PACKAGE_NAME as NAME, PACKAGE_TEXT as TEXT, PROGRAM_SCHEMA as BASE_SCHEMA, PROGRAM_NAME as BASE_OBJ `,
99+
`from QSYS2.SQLPACKAGE`,
92100
`where PACKAGE_SCHEMA = '${schema}' ${details.filter ? `and PACKAGE_NAME like '%${details.filter}%'`: ``}`,
93-
`order by PACKAGE_NAME asc`,
94-
`${details.limit ? `limit ${details.limit}` : ``} ${details.offset ? `offset ${details.offset}` : ``}`
95-
].join(` `));
101+
`order by PACKAGE_NAME asc`
102+
].join(` `);
96103
break;
97104

98105
case `triggers`:
99-
objects = await JobManager.runSQL([
100-
`select TRIGGER_NAME as NAME, TRIGGER_TEXT as TEXT, EVENT_OBJECT_SCHEMA as BASE_SCHEMA, EVENT_OBJECT_TABLE as BASE_OBJ from QSYS2.SYSTRIGGERS`,
106+
query = [
107+
`select TRIGGER_NAME as NAME, TRIGGER_TEXT as TEXT, EVENT_OBJECT_SCHEMA as BASE_SCHEMA, EVENT_OBJECT_TABLE as BASE_OBJ `,
108+
`from QSYS2.SYSTRIGGERS`,
101109
`where TRIGGER_SCHEMA = '${schema}' ${details.filter ? `and TRIGGER_NAME like '%${details.filter}%'`: ``}`,
102-
`order by TRIGGER_NAME asc`,
103-
`${details.limit ? `limit ${details.limit}` : ``} ${details.offset ? `offset ${details.offset}` : ``}`
104-
].join(` `));
110+
`order by TRIGGER_NAME asc`
111+
].join(` `);
105112
break;
106113

107114
case `types`:
108-
objects = await JobManager.runSQL([
109-
`select USER_DEFINED_TYPE_NAME as NAME, TYPE_TEXT as TEXT, SYSTEM_TYPE_NAME as SYS_NAME, SYSTEM_TYPE_SCHEMA as SYS_SCHEMA from QSYS2.SYSTYPES`,
115+
query = [
116+
`select USER_DEFINED_TYPE_NAME as NAME, TYPE_TEXT as TEXT, SYSTEM_TYPE_NAME as SYS_NAME, SYSTEM_TYPE_SCHEMA as SYS_SCHEMA `,
117+
`from QSYS2.SYSTYPES`,
110118
`where USER_DEFINED_TYPE_SCHEMA = '${schema}' ${details.filter ? `and USER_DEFINED_TYPE_NAME like '%${details.filter}%'`: ``}`,
111-
`order by USER_DEFINED_TYPE_NAME asc`,
112-
`${details.limit ? `limit ${details.limit}` : ``} ${details.offset ? `offset ${details.offset}` : ``}`
113-
].join(` `));
119+
`order by USER_DEFINED_TYPE_NAME asc`
120+
].join(` `);
114121
break;
115122
}
116123

117-
return objects.map(table => ({
124+
let objects : any[] = await JobManager.runSQL([
125+
query,
126+
`${details.limit ? `limit ${details.limit}` : ``} ${details.offset ? `offset ${details.offset}` : ``}`
127+
].join(` `));
128+
129+
return objects.map(object => ({
118130
type,
119131
schema,
120-
name: table.NAME,
121-
text: table.TEXT,
132+
name: object.NAME,
133+
specificName: object.SPECNAME,
134+
text: object.TEXT,
122135
system: {
123-
schema: table.SYS_SCHEMA,
124-
name: table.SYS_NAME,
136+
schema: object.SYS_SCHEMA,
137+
name: object.SYS_NAME,
125138
},
126139
basedOn: {
127-
schema: table.BASE_SCHEMA,
128-
name: table.BASE_OBJ
140+
schema: object.BASE_SCHEMA,
141+
name: object.BASE_OBJ
129142
}
130143
}));
131144
}
@@ -137,7 +150,7 @@ export default class Database {
137150
static async generateSQL(schema: string, object: string, internalType: string): Promise<string> {
138151
const lines = await JobManager.runSQL<{SRCDTA: string}>([
139152
`CALL QSYS2.GENERATE_SQL(?, ?, ?, CREATE_OR_REPLACE_OPTION => '1', PRIVILEGES_OPTION => '0')`
140-
].join(` `), [object, schema, internalType]);
153+
].join(` `), { parameters : [object, schema, internalType] });
141154

142155
const generatedStatement = lines.map(line => line.SRCDTA).join(`\n`);
143156
const formatted = Statement.format(generatedStatement);
@@ -146,12 +159,16 @@ export default class Database {
146159
}
147160

148161
static async deleteObject(schema: string, name:string, type: string): Promise<void> {
149-
const query = `DROP ${type} IF EXISTS ${schema}.${name}`;
162+
const query = `DROP ${(this.isRoutineType(type) ? 'SPECIFIC ' : '') + type} IF EXISTS ${schema}.${name}`;
150163
await getInstance().getContent().runSQL(query);
151164
}
152165

153166
static async renameObject(schema: string, oldName: string, newName: string, type: string): Promise<void> {
154167
const query = `RENAME ${type === 'view' ? 'table' : type} ${schema}.${oldName} TO ${newName}`;
155168
await getInstance().getContent().runSQL(query);
156169
}
170+
171+
static isRoutineType(type: string): boolean {
172+
return type === `function` || type === `procedure`;
173+
}
157174
}

0 commit comments

Comments
 (0)