Skip to content

Commit 1840fc0

Browse files
committed
Use binding parameters for schema filters
Signed-off-by: worksofliam <[email protected]>
1 parent 5db8e5c commit 1840fc0

File tree

1 file changed

+65
-20
lines changed

1 file changed

+65
-20
lines changed

src/database/schemas.ts

Lines changed: 65 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -16,22 +16,31 @@ export const AllSQLTypes: SQLType[] = ["tables", "views", "aliases", "constraint
1616

1717
export const SQL_ESCAPE_CHAR = `\\`;
1818

19-
function getFilterClause(againstColumn: string, filter: string|undefined, noAnd?: boolean): string {
19+
type BasicColumnType = string|number;
20+
interface PartStatementInfo {clause: string, parameters: BasicColumnType[]};
21+
22+
function getFilterClause(againstColumn: string, filter: string, noAnd?: boolean): PartStatementInfo {
2023
if (!filter) {
21-
return ``;
24+
return {clause: ``, parameters: []};
2225
}
2326

24-
let clause = `${noAnd ? '' : 'AND '} UPPER(${againstColumn})`;
27+
let clause = `${noAnd ? '' : 'AND'} UPPER(${againstColumn})`;
28+
let parameters: BasicColumnType[] = [];
2529

2630
if (filter.endsWith(`*`)) {
27-
clause += ` LIKE '${filter.slice(0, -1).toUpperCase()}%'`;
31+
clause += ` LIKE ? CONCAT '%'`;
32+
parameters.push(filter.slice(0, -1).toUpperCase());
2833
} else {
29-
clause += ` LIKE '%${filter.toUpperCase()}%'`;
34+
clause += ` LIKE '%' CONCAT ? CONCAT '%'`;
35+
parameters.push(filter.toUpperCase());
3036
}
3137

32-
clause += ` ESCAPE '${SQL_ESCAPE_CHAR}'`;
38+
// clause += ` ESCAPE '${SQL_ESCAPE_CHAR}'`;
3339

34-
return clause;
40+
return {
41+
clause,
42+
parameters
43+
};
3544
}
3645

3746
export default class Schemas {
@@ -40,6 +49,8 @@ export default class Schemas {
4049
*/
4150
static async getObjects(schema: string, types: SQLType[], details: PageData = {}): Promise<BasicSQLObject[]> {
4251
const selects: string[] = [];
52+
let parameters: (string|number)[] = [];
53+
let filter: PartStatementInfo;
4354

4455
// If there are multiple types, we build a union. It's important that the ordering of the columns in the selects are consistant:
4556
// OBJ_TYPE, NAME, TEXT, SYS_NAME, SYS_SCHEMA, SPECNAME, BASE_SCHEMA, BASE_OBJ
@@ -50,101 +61,135 @@ export default class Schemas {
5061
selects.push([
5162
`select '${type}' as OBJ_TYPE, SCHEMA_NAME as NAME, SCHEMA_TEXT as TEXT, SYSTEM_SCHEMA_NAME as SYS_NAME, '' as SYS_SCHEMA, '' as SPECNAME, '' as BASE_SCHEMA, '' as BASE_OBJ`,
5263
`from QSYS2.SYSSCHEMAS`,
53-
details.filter ? `where UPPER(SCHEMA_NAME) = '${details.filter}' or UPPER(SYSTEM_SCHEMA_NAME) = '${details.filter}'` : ``,
64+
details.filter ? `where UPPER(SCHEMA_NAME) = ? or UPPER(SYSTEM_SCHEMA_NAME) = ?` : ``,
5465
].join(` `));
66+
67+
parameters.push(details.filter, details.filter);
5568
break;
5669

5770
case `tables`:
5871
case `views`:
5972
case `aliases`:
73+
filter = getFilterClause(`TABLE_NAME`, details.filter);
6074
selects.push([
6175
`select '${type}' as OBJ_TYPE, TABLE_NAME as NAME, TABLE_TEXT as TEXT, SYSTEM_TABLE_NAME as SYS_NAME, SYSTEM_TABLE_SCHEMA as SYS_SCHEMA, '' as SPECNAME, BASE_TABLE_SCHEMA as BASE_SCHEMA, BASE_TABLE_NAME as BASE_OBJ`,
6276
`from QSYS2.SYSTABLES`,
63-
`where TABLE_SCHEMA = '${schema}' and TABLE_TYPE in (${typeMap[type].map(item => `'${item}'`).join(`, `)}) ${getFilterClause(`TABLE_NAME`, details.filter)}`,
77+
`where TABLE_SCHEMA = ? and TABLE_TYPE in (${typeMap[type].map(item => `'${item}'`).join(`, `)}) ${filter.clause}`,
6478
].join(` `));
79+
80+
parameters.push(schema, ...filter.parameters);
6581
break;
6682

6783
case `constraints`:
84+
filter = getFilterClause(`CONSTRAINT_NAME`, details.filter);
6885
selects.push([
6986
`select '${type}' as OBJ_TYPE, CONSTRAINT_NAME as NAME, CONSTRAINT_TEXT as TEXT, SYSTEM_TABLE_NAME as SYS_NAME, SYSTEM_TABLE_SCHEMA as SYS_SCHEMA, '' as SPECNAME, TABLE_SCHEMA as BASE_SCHEMA, TABLE_NAME as BASE_OBJ`,
7087
`from QSYS2.SYSCST`,
71-
`where CONSTRAINT_SCHEMA = '${schema}' ${getFilterClause(`CONSTRAINT_NAME`, details.filter)}`,
88+
`where CONSTRAINT_SCHEMA = ? ${filter.clause}`,
7289
].join(` `));
90+
91+
parameters.push(schema, ...filter.parameters);
7392
break;
7493

7594
case `functions`:
95+
filter = getFilterClause(`ROUTINE_NAME`, details.filter);
7696
selects.push([
7797
`select '${type}' as OBJ_TYPE, ROUTINE_NAME as NAME, coalesce(ROUTINE_TEXT, LONG_COMMENT) as TEXT, '' as SYS_NAME, '' as SYS_SCHEMA, SPECIFIC_NAME as SPECNAME, '' as BASE_SCHEMA, '' as BASE_OBJ`,
7898
`from QSYS2.SYSFUNCS`,
79-
`where ROUTINE_SCHEMA = '${schema}' ${getFilterClause(`ROUTINE_NAME`, details.filter)} and FUNCTION_ORIGIN in ('E','U')`,
99+
`where ROUTINE_SCHEMA = ? ${filter.clause} and FUNCTION_ORIGIN in ('E','U')`,
80100
].join(` `));
101+
102+
parameters.push(schema, ...filter.parameters);
81103
break;
82104

83105
case `variables`:
106+
filter = getFilterClause(`VARIABLE_NAME`, details.filter);
84107
selects.push([
85108
`select '${type}' as OBJ_TYPE, VARIABLE_NAME as NAME, VARIABLE_TEXT as TEXT, SYSTEM_VAR_NAME as SYS_NAME, SYSTEM_VAR_SCHEMA as SYS_SCHEMA, '' as SPECNAME, '' as BASE_SCHEMA, '' as BASE_OBJ`,
86109
`from QSYS2.SYSVARIABLES`,
87-
`where VARIABLE_SCHEMA = '${schema}' ${getFilterClause(`VARIABLE_NAME`, details.filter)}`,
110+
`where VARIABLE_SCHEMA = ? ${filter.clause}`,
88111
].join(` `));
112+
113+
parameters.push(schema, ...filter.parameters);
89114
break;
90115

91116
case `indexes`:
117+
filter = getFilterClause(`INDEX_NAME`, details.filter);
92118
selects.push([
93119
`select '${type}' as OBJ_TYPE, INDEX_NAME as NAME, INDEX_TEXT as TEXT, SYSTEM_INDEX_NAME as SYS_NAME, SYSTEM_INDEX_SCHEMA as SYS_SCHEMA, '' as SPECNAME, TABLE_SCHEMA as BASE_SCHEMA, TABLE_NAME as BASE_OBJ`,
94120
`from QSYS2.SYSINDEXES`,
95-
`where INDEX_SCHEMA = '${schema}' ${getFilterClause(`INDEX_NAME`, details.filter)}`,
121+
`where INDEX_SCHEMA = ? ${filter.clause}`,
96122
].join(` `));
123+
124+
parameters.push(schema, ...filter.parameters);
97125
break;
98126

99127
case `procedures`:
128+
filter = getFilterClause(`ROUTINE_NAME`, details.filter);
100129
selects.push([
101130
`select '${type}' as OBJ_TYPE, ROUTINE_NAME as NAME, ROUTINE_TEXT as TEXT, '' as SYS_NAME, '' as SYS_SCHEMA, SPECIFIC_NAME as SPECNAME, '' as BASE_SCHEMA, '' as BASE_OBJ`,
102131
`from QSYS2.SYSPROCS`,
103-
`where ROUTINE_SCHEMA = '${schema}' ${getFilterClause(`ROUTINE_NAME`, details.filter)}`,
132+
`where ROUTINE_SCHEMA = ? ${filter.clause}`,
104133
].join(` `));
134+
135+
parameters.push(schema, ...filter.parameters);
105136
break;
106137

107138
case `sequences`:
139+
filter = getFilterClause(`SEQUENCE_NAME`, details.filter);
108140
selects.push([
109141
`select '${type}' as OBJ_TYPE, SEQUENCE_NAME as NAME, SEQUENCE_TEXT as TEXT, SYSTEM_SEQ_NAME as SYS_NAME, SYSTEM_SEQ_SCHEMA as SYS_SCHEMA, '' as SPECNAME, '' as BASE_SCHEMA, '' as BASE_OBJ`,
110142
`from QSYS2.SYSSEQUENCES`,
111-
`where SEQUENCE_SCHEMA = '${schema}' ${getFilterClause(`SEQUENCE_NAME`, details.filter)}`,
143+
`where SEQUENCE_SCHEMA = ? ${filter.clause}`,
112144
].join(` `));
145+
146+
parameters.push(schema, ...filter.parameters);
113147
break;
114148

115149
// case `packages`:
116150
// selects.push([
117151
// `select '${type}' as OBJ_TYPE, PACKAGE_NAME as NAME, PACKAGE_TEXT as TEXT, PROGRAM_SCHEMA as BASE_SCHEMA, PROGRAM_NAME as BASE_OBJ, `,
118152
// ` '' as SYS_SCHEMA, '' as SYS_NAME, '' as SPECNAME`,
119153
// `from QSYS2.SQLPACKAGE`,
120-
// `where PACKAGE_SCHEMA = '${schema}' ${details.filter ? `and PACKAGE_NAME like '%${details.filter}%'`: ``}`,
154+
// `where PACKAGE_SCHEMA = '${schema}' ${details.filter ? `and PACKAGE_NAME like '%${filter.clause}%'`: ``}`,
121155
// ].join(` `));
122156
// break;
123157

124158
case `triggers`:
159+
filter = getFilterClause(`TRIGGER_NAME`, details.filter);
125160
selects.push([
126161
`select '${type}' as OBJ_TYPE, TRIGGER_NAME as NAME, TRIGGER_TEXT as TEXT, '' as SYS_NAME, '' as SYS_SCHEMA, '' as SPECNAME, EVENT_OBJECT_SCHEMA as BASE_SCHEMA, EVENT_OBJECT_TABLE as BASE_OBJ`,
127162
`from QSYS2.SYSTRIGGERS`,
128-
`where TRIGGER_SCHEMA = '${schema}' ${getFilterClause(`TRIGGER_NAME`, details.filter)}`,
163+
`where TRIGGER_SCHEMA = ? ${filter.clause}`,
129164
].join(` `));
165+
166+
parameters.push(schema, ...filter.parameters);
130167
break;
131168

132169
case `types`:
170+
filter = getFilterClause(`USER_DEFINED_TYPE_NAME`, details.filter);
133171
selects.push([
134172
`select '${type}' as OBJ_TYPE, USER_DEFINED_TYPE_NAME as NAME, TYPE_TEXT as TEXT, SYSTEM_TYPE_NAME as SYS_NAME, SYSTEM_TYPE_SCHEMA as SYS_SCHEMA, '' as SPECNAME, '' as BASE_SCHEMA, '' as BASE_OBJ`,
135173
`from QSYS2.SYSTYPES`,
136-
`where USER_DEFINED_TYPE_SCHEMA = '${schema}' ${getFilterClause(`USER_DEFINED_TYPE_NAME`, details.filter)}`,
174+
`where USER_DEFINED_TYPE_SCHEMA = ? ${filter.clause}`,
137175
].join(` `));
176+
177+
parameters.push(schema, ...filter.parameters);
138178
break;
139179
}
140180
}
141181

142182
const query = `with results as (${selects.join(" UNION ALL ")}) select * from results Order by QSYS2.DELIMIT_NAME(NAME) asc`;
143183

144-
const objects: any[] = await JobManager.runSQL([
184+
const objects: any[] = await JobManager.runSQL(
185+
[
145186
query,
146187
`${details.limit ? `limit ${details.limit}` : ``} ${details.offset ? `offset ${details.offset}` : ``}`
147-
].join(` `));
188+
].join(` `),
189+
{
190+
parameters
191+
}
192+
);
148193

149194
return objects.map(object => ({
150195
type: object.OBJ_TYPE,

0 commit comments

Comments
 (0)