Skip to content

Commit eedcba4

Browse files
committed
Go to defintion now resolves based on library list
Signed-off-by: worksofliam <[email protected]>
1 parent 87ad327 commit eedcba4

File tree

2 files changed

+71
-80
lines changed

2 files changed

+71
-80
lines changed

src/database/schemas.ts

Lines changed: 68 additions & 66 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ const typeMap = {
1616

1717
export const AllSQLTypes: SQLType[] = ["tables", "views", "aliases", "constraints", "functions", "variables", "indexes", "procedures", "sequences", "packages", "triggers", "types", "logicals"];
1818

19-
export const InternalTypes: {[t: string]: string} = {
19+
export const InternalTypes: { [t: string]: string } = {
2020
"tables": `table`,
2121
"views": `view`,
2222
"aliases": `alias`,
@@ -34,12 +34,12 @@ export const InternalTypes: {[t: string]: string} = {
3434

3535
export const SQL_ESCAPE_CHAR = `\\`;
3636

37-
type BasicColumnType = string|number;
38-
interface PartStatementInfo {clause: string, parameters: BasicColumnType[]};
37+
type BasicColumnType = string | number;
38+
interface PartStatementInfo { clause: string, parameters: BasicColumnType[] };
3939

4040
function getFilterClause(againstColumn: string, filter: string, noAnd?: boolean): PartStatementInfo {
4141
if (!filter) {
42-
return {clause: ``, parameters: []};
42+
return { clause: ``, parameters: [] };
4343
}
4444

4545
let clause = `${noAnd ? '' : 'AND'} UPPER(${againstColumn})`;
@@ -63,7 +63,7 @@ function getFilterClause(againstColumn: string, filter: string, noAnd?: boolean)
6363
};
6464
}
6565

66-
export interface ObjectReference {name: string, schema?: string};
66+
export interface ObjectReference { name: string, schema?: string };
6767

6868
const BASE_RESOLVE_SELECT = [
6969
`select `,
@@ -91,14 +91,7 @@ export default class Schemas {
9191
let resolvedObjects: ResolvedSqlObject[] = [];
9292

9393
// We need to remove any duplicates from the list of objects to resolve
94-
const uniqueObjects = new Set<string>();
95-
sqlObjects = sqlObjects.filter((obj) => {
96-
if (!uniqueObjects.has(obj.name)) {
97-
uniqueObjects.add(obj.name);
98-
return true;
99-
}
100-
return false;
101-
});
94+
sqlObjects = sqlObjects.filter(o => sqlObjects.indexOf(o) === sqlObjects.findIndex(obj => obj.name === o.name && obj.schema === o.schema));
10295

10396
// First, we use OBJECT_STATISTICS to resolve the object based on the library list.
10497
// But, if the object is qualified with a schema, we need to use that schema to get the correct object.
@@ -130,52 +123,64 @@ export default class Schemas {
130123
.map((obj) => obj.name);
131124
const qualified = sqlObjects.filter((obj) => obj.schema);
132125

133-
let baseStatement = [
134-
`select s.routine_name as name, l.schema_name as schema, s.ROUTINE_TYPE as sqlType`,
135-
`from qsys2.library_list_info as l`,
136-
`right join qsys2.sysroutines as s on l.schema_name = s.routine_schema`,
137-
`where `,
138-
` l.schema_name is not null and`,
139-
` s.routine_name in (${unqualified.map(() => `?`).join(`, `)})`,
140-
].join(` `);
141-
parameters.push(...unqualified);
142-
143-
if (qualified.length > 0) {
144-
const qualifiedClause = qualified
145-
.map((obj) => `(s.routine_name = ? AND s.routine_schema = ?)`)
146-
.join(` OR `);
147-
baseStatement += ` and (${qualifiedClause})`;
148-
parameters.push(...qualified.flatMap((obj) => [obj.name, obj.schema]));
149-
}
126+
if (qualified.length && unqualified.length) {
127+
let baseStatement = [
128+
`select s.routine_name as name, l.schema_name as schema, s.ROUTINE_TYPE as sqlType`,
129+
`from qsys2.library_list_info as l`,
130+
`right join qsys2.sysroutines as s on l.schema_name = s.routine_schema`,
131+
`where `,
132+
` l.schema_name is not null`,
133+
].join(` `);
134+
135+
if (unqualified.length > 0) {
136+
baseStatement += ` and s.routine_name in (${unqualified.map(() => `?`).join(`, `)})`;
137+
parameters.push(...unqualified);
138+
}
150139

151-
statements.push(baseStatement);
140+
if (qualified.length > 0) {
141+
const qualifiedClause = qualified
142+
.map((obj) => `(s.routine_name = ? AND s.routine_schema = ?)`)
143+
.join(` OR `);
144+
baseStatement += ` and (${qualifiedClause})`;
145+
parameters.push(...qualified.flatMap((obj) => [obj.name, obj.schema]));
146+
}
147+
148+
statements.push(baseStatement);
149+
}
152150

153151
if (statements.length === 0) {
154-
return [];
152+
return resolvedObjects;
155153
}
156154

157155
const query = `${statements.join(" UNION ALL ")}`;
158-
const objects: any[] = await JobManager.runSQL(query, { parameters });
159-
160-
resolvedObjects.push(
161-
...objects
162-
.map((object) => ({
163-
name: object.NAME,
164-
schema: object.SCHEMA,
165-
sqlType: object.SQLTYPE,
166-
}))
167-
.filter((o) => o.sqlType)
168-
);
169-
170-
// add reslved objects to to ReferenceCache
171-
resolvedObjects.forEach((obj) => {
172-
const key = this.buildReferenceCacheKey(obj);
173-
if (!ReferenceCache.has(key)) {
174-
ReferenceCache.set(key, obj);
175-
}
176-
});
177156

178-
return resolvedObjects;
157+
try {
158+
const objects: any[] = await JobManager.runSQL(query, { parameters });
159+
160+
resolvedObjects.push(
161+
...objects
162+
.map((object) => ({
163+
name: object.NAME,
164+
schema: object.SCHEMA,
165+
sqlType: object.SQLTYPE,
166+
}))
167+
.filter((o) => o.sqlType)
168+
);
169+
170+
// add reslved objects to to ReferenceCache
171+
resolvedObjects.forEach((obj) => {
172+
const key = this.buildReferenceCacheKey(obj);
173+
if (!ReferenceCache.has(key)) {
174+
ReferenceCache.set(key, obj);
175+
}
176+
});
177+
178+
return resolvedObjects;
179+
} catch (e) {
180+
console.warn(`Error resolving objects: ${JSON.stringify(sqlObjects)}`);
181+
console.warn(e);
182+
return [];
183+
}
179184
}
180185

181186
static async getRelatedObjects(
@@ -376,8 +381,7 @@ export default class Schemas {
376381
const objects: any[] = await JobManager.runSQL(
377382
[
378383
query,
379-
`${details.limit ? `limit ${details.limit}` : ``} ${
380-
details.offset ? `offset ${details.offset}` : ``
384+
`${details.limit ? `limit ${details.limit}` : ``} ${details.offset ? `offset ${details.offset}` : ``
381385
}`,
382386
].join(` `),
383387
{
@@ -442,12 +446,12 @@ export default class Schemas {
442446
`CALL QSYS2.GENERATE_SQL( ${options.join(`, `)} )`,
443447
].join(` `), { parameters: [object, schema, internalType] });
444448

445-
// TODO: eventually .content -> .getContent(), it's not available yet
446-
const contents = (
447-
await connection.content.downloadStreamfileRaw(tempFilePath)
448-
).toString();
449-
return contents;
450-
}
449+
// TODO: eventually .content -> .getContent(), it's not available yet
450+
const contents = (
451+
await connection.content.downloadStreamfileRaw(tempFilePath)
452+
).toString();
453+
return contents;
454+
}
451455
);
452456

453457
return result;
@@ -458,9 +462,8 @@ export default class Schemas {
458462
name: string,
459463
type: string
460464
): Promise<void> {
461-
const query = `DROP ${
462-
(this.isRoutineType(type) ? "SPECIFIC " : "") + type
463-
} IF EXISTS ${schema}.${name}`;
465+
const query = `DROP ${(this.isRoutineType(type) ? "SPECIFIC " : "") + type
466+
} IF EXISTS ${schema}.${name}`;
464467
await getInstance().getContent().runSQL(query);
465468
}
466469

@@ -470,9 +473,8 @@ export default class Schemas {
470473
newName: string,
471474
type: string
472475
): Promise<void> {
473-
const query = `RENAME ${
474-
type === "view" ? "table" : type
475-
} ${schema}.${oldName} TO ${newName}`;
476+
const query = `RENAME ${type === "view" ? "table" : type
477+
} ${schema}.${oldName} TO ${newName}`;
476478
await getInstance().getContent().runSQL(query);
477479
}
478480

src/language/providers/peekProvider.ts

Lines changed: 3 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -28,24 +28,13 @@ export const peekProvider = languages.registerDefinitionProvider({ language: `sq
2828
const name = Statement.noQuotes(Statement.delimName(ref.object.name, true));
2929
const schema = Statement.noQuotes(Statement.delimName(ref.object.schema || defaultSchema, true));
3030

31-
let types: SQLType[] = standardObjects;
32-
33-
if (ref.isUDTF) {
34-
types = [`functions`];
35-
} else if (statementAt.type === StatementType.Call) {
36-
types = [`procedures`];
37-
}
38-
39-
const possibleObjects = await Schemas.getObjects(schema, types, {filter: name});
31+
const possibleObjects = await Schemas.resolveObjects([{name, schema}]);
4032

4133
if (possibleObjects.length) {
4234
const lines: string[] = [`-- Condensed version of the object definition`];
4335
for (const obj of possibleObjects) {
44-
const type = InternalTypes[obj.type];
45-
if (type) {
46-
const contents = await Schemas.generateSQL(obj.schema, obj.name, type.toUpperCase(), true);
47-
lines.push(contents, ``, ``);
48-
}
36+
const contents = await Schemas.generateSQL(obj.schema, obj.name, obj.sqlType, true);
37+
lines.push(contents);
4938
}
5039

5140
const document = await workspace.openTextDocument({ content: lines.join(`\n`), language: `sql` });

0 commit comments

Comments
 (0)