-
-
Notifications
You must be signed in to change notification settings - Fork 4.2k
/
query-generator-typescript.ts
205 lines (183 loc) · 8.4 KB
/
query-generator-typescript.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
import { rejectInvalidOptions } from '../../utils/check';
import { joinSQLFragments } from '../../utils/join-sql-fragments';
import { generateIndexName } from '../../utils/string';
import { AbstractQueryGenerator } from '../abstract/query-generator';
import {
REMOVE_INDEX_QUERY_SUPPORTABLE_OPTIONS,
RENAME_TABLE_QUERY_SUPPORTABLE_OPTIONS,
} from '../abstract/query-generator-typescript';
import type { RemoveIndexQueryOptions, TableNameOrModel } from '../abstract/query-generator-typescript';
import type {
AddLimitOffsetOptions,
ListSchemasQueryOptions,
ListTablesQueryOptions,
RenameTableQueryOptions,
ShowConstraintsQueryOptions,
} from '../abstract/query-generator.types';
const REMOVE_INDEX_QUERY_SUPPORTED_OPTIONS = new Set<keyof RemoveIndexQueryOptions>(['ifExists']);
const RENAME_TABLE_QUERY_SUPPORTED_OPTIONS = new Set<keyof RenameTableQueryOptions>();
/**
* Temporary class to ease the TypeScript migration
*/
export class IBMiQueryGeneratorTypeScript extends AbstractQueryGenerator {
listSchemasQuery(options?: ListSchemasQueryOptions) {
return joinSQLFragments([
`SELECT DISTINCT SCHEMA_NAME AS "schema" FROM QSYS2.SYSSCHEMAAUTH WHERE GRANTEE = CURRENT USER`,
`AND SCHEMA_NAME NOT LIKE 'Q%' AND SCHEMA_NAME NOT LIKE 'SYS%'`,
options?.skip && Array.isArray(options.skip) && options.skip.length > 0
? `AND SCHEMA_NAME NOT IN (${options?.skip.map(schema => this.escape(schema)).join(', ')})`
: '',
]);
}
describeTableQuery(tableName: TableNameOrModel) {
const table = this.extractTableDetails(tableName);
return joinSQLFragments([
'SELECT',
'QSYS2.SYSCOLUMNS.*,',
'QSYS2.SYSCST.CONSTRAINT_NAME,',
'QSYS2.SYSCST.CONSTRAINT_TYPE',
'FROM QSYS2.SYSCOLUMNS',
'LEFT OUTER JOIN QSYS2.SYSCSTCOL',
'ON QSYS2.SYSCOLUMNS.TABLE_SCHEMA = QSYS2.SYSCSTCOL.TABLE_SCHEMA',
'AND QSYS2.SYSCOLUMNS.TABLE_NAME = QSYS2.SYSCSTCOL.TABLE_NAME',
'AND QSYS2.SYSCOLUMNS.COLUMN_NAME = QSYS2.SYSCSTCOL.COLUMN_NAME',
'LEFT JOIN QSYS2.SYSCST',
'ON QSYS2.SYSCSTCOL.CONSTRAINT_NAME = QSYS2.SYSCST.CONSTRAINT_NAME',
'WHERE QSYS2.SYSCOLUMNS.TABLE_SCHEMA =',
table.schema ? this.escape(table.schema) : 'CURRENT SCHEMA',
'AND QSYS2.SYSCOLUMNS.TABLE_NAME =',
this.escape(table.tableName),
]);
}
listTablesQuery(options?: ListTablesQueryOptions) {
return joinSQLFragments([
'SELECT TABLE_NAME AS "tableName",',
'TABLE_SCHEMA AS "schema"',
`FROM QSYS2.SYSTABLES WHERE TABLE_TYPE = 'T'`,
options?.schema
? `AND TABLE_SCHEMA = ${this.escape(options.schema)}`
: `AND TABLE_SCHEMA NOT LIKE 'Q%' AND TABLE_SCHEMA NOT LIKE 'SYS%'`,
'ORDER BY TABLE_SCHEMA, TABLE_NAME',
]);
}
renameTableQuery(
beforeTableName: TableNameOrModel,
afterTableName: TableNameOrModel,
options?: RenameTableQueryOptions,
): string {
if (options) {
rejectInvalidOptions(
'renameTableQuery',
this.dialect.name,
RENAME_TABLE_QUERY_SUPPORTABLE_OPTIONS,
RENAME_TABLE_QUERY_SUPPORTED_OPTIONS,
options,
);
}
const beforeTable = this.extractTableDetails(beforeTableName);
const afterTable = this.extractTableDetails(afterTableName);
if (beforeTable.schema !== afterTable.schema) {
throw new Error(`Moving tables between schemas is not supported by ${this.dialect.name} dialect.`);
}
return `RENAME TABLE ${this.quoteTable(beforeTableName)} TO ${this.quoteIdentifier(afterTable.tableName)}`;
}
showConstraintsQuery(tableName: TableNameOrModel, options?: ShowConstraintsQueryOptions) {
const table = this.extractTableDetails(tableName);
return joinSQLFragments([
'SELECT c.CONSTRAINT_SCHEMA AS "constraintSchema",',
'c.CONSTRAINT_NAME AS "constraintName",',
'c.CONSTRAINT_TYPE AS "constraintType",',
'c.TABLE_SCHEMA AS "tableSchema",',
'c.TABLE_NAME AS "tableName",',
'k.COLUMN_NAME AS "columnNames",',
'fk.TABLE_SCHEMA AS "referencedTableSchema",',
'fk.TABLE_NAME AS "referencedTableName",',
'fk.COLUMN_NAME AS "referencedColumnNames",',
'r.DELETE_RULE AS "deleteRule",',
'r.UPDATE_RULE AS "updateRule",',
'ch.CHECK_CLAUSE AS "definition",',
'c.IS_DEFERRABLE AS "isDeferrable",',
'c.INITIALLY_DEFERRED AS "initiallyDeferred"',
'FROM QSYS2.SYSCST c',
'LEFT JOIN QSYS2.SYSREFCST r ON c.CONSTRAINT_NAME = r.CONSTRAINT_NAME AND c.CONSTRAINT_SCHEMA = r.CONSTRAINT_SCHEMA',
'LEFT JOIN QSYS2.SYSKEYCST k ON c.CONSTRAINT_NAME = k.CONSTRAINT_NAME AND c.CONSTRAINT_SCHEMA = k.CONSTRAINT_SCHEMA',
'LEFT JOIN QSYS2.SYSKEYCST fk ON r.UNIQUE_CONSTRAINT_NAME = k.CONSTRAINT_NAME AND r.UNIQUE_CONSTRAINT_SCHEMA = k.CONSTRAINT_SCHEMA',
'LEFT JOIN QSYS2.SYSCHKCST ch ON c.CONSTRAINT_NAME = ch.CONSTRAINT_NAME AND c.CONSTRAINT_SCHEMA = ch.CONSTRAINT_SCHEMA',
`WHERE c.TABLE_NAME = ${this.escape(table.tableName)}`,
'AND c.TABLE_SCHEMA =',
table.schema ? this.escape(table.schema) : 'CURRENT SCHEMA',
options?.columnName ? `AND k.COLUMN_NAME = ${this.escape(options.columnName)}` : '',
options?.constraintName ? `AND c.CONSTRAINT_NAME = ${this.escape(options.constraintName)}` : '',
options?.constraintType ? `AND c.CONSTRAINT_TYPE = ${this.escape(options.constraintType)}` : '',
'ORDER BY c.CONSTRAINT_NAME, k.ORDINAL_POSITION, fk.ORDINAL_POSITION',
]);
}
showIndexesQuery(tableName: TableNameOrModel) {
const table = this.extractTableDetails(tableName);
// TODO [+odbc]: check if the query also works when capitalized (for consistency)
return joinSQLFragments([
'select QSYS2.SYSCSTCOL.CONSTRAINT_NAME as NAME, QSYS2.SYSCSTCOL.COLUMN_NAME, QSYS2.SYSCST.CONSTRAINT_TYPE, QSYS2.SYSCST.TABLE_SCHEMA,',
'QSYS2.SYSCST.TABLE_NAME from QSYS2.SYSCSTCOL left outer join QSYS2.SYSCST on QSYS2.SYSCSTCOL.TABLE_SCHEMA = QSYS2.SYSCST.TABLE_SCHEMA and',
'QSYS2.SYSCSTCOL.TABLE_NAME = QSYS2.SYSCST.TABLE_NAME and QSYS2.SYSCSTCOL.CONSTRAINT_NAME = QSYS2.SYSCST.CONSTRAINT_NAME where',
'QSYS2.SYSCSTCOL.TABLE_SCHEMA =',
table.schema ? this.escape(table.schema) : 'CURRENT SCHEMA',
`and QSYS2.SYSCSTCOL.TABLE_NAME = ${this.escape(table.tableName)} union select QSYS2.SYSKEYS.INDEX_NAME AS NAME,`,
`QSYS2.SYSKEYS.COLUMN_NAME, CAST('INDEX' AS VARCHAR(11)), QSYS2.SYSINDEXES.TABLE_SCHEMA, QSYS2.SYSINDEXES.TABLE_NAME from QSYS2.SYSKEYS`,
'left outer join QSYS2.SYSINDEXES on QSYS2.SYSKEYS.INDEX_NAME = QSYS2.SYSINDEXES.INDEX_NAME where QSYS2.SYSINDEXES.TABLE_SCHEMA =',
table.schema ? this.escape(table.schema) : 'CURRENT SCHEMA',
'and QSYS2.SYSINDEXES.TABLE_NAME =',
this.escape(table.tableName),
]);
}
removeIndexQuery(
tableName: TableNameOrModel,
indexNameOrAttributes: string | string[],
options?: RemoveIndexQueryOptions,
) {
if (options) {
rejectInvalidOptions(
'removeIndexQuery',
this.dialect.name,
REMOVE_INDEX_QUERY_SUPPORTABLE_OPTIONS,
REMOVE_INDEX_QUERY_SUPPORTED_OPTIONS,
options,
);
}
let indexName: string;
if (Array.isArray(indexNameOrAttributes)) {
const table = this.extractTableDetails(tableName);
indexName = generateIndexName(table, { fields: indexNameOrAttributes });
} else {
indexName = indexNameOrAttributes;
}
return joinSQLFragments([
'BEGIN',
options?.ifExists ? `IF EXISTS (SELECT * FROM QSYS2.SYSINDEXES WHERE INDEX_NAME = ${this.quoteIdentifier(indexName)}) THEN` : '',
`DROP INDEX ${this.quoteIdentifier(indexName)};`,
'COMMIT;',
options?.ifExists ? 'END IF;' : '',
'END',
]);
}
// Version queries
versionQuery() {
return `SELECT CONCAT(OS_VERSION, CONCAT('.', OS_RELEASE)) AS "version" FROM SYSIBMADM.ENV_SYS_INFO`;
}
tableExistsQuery(tableName: TableNameOrModel): string {
const table = this.extractTableDetails(tableName);
return joinSQLFragments([
`SELECT TABLE_NAME FROM QSYS2.SYSTABLES WHERE TABLE_NAME = ${this.escape(table.tableName)} AND TABLE_SCHEMA = `,
table.schema ? this.escape(table.schema) : 'CURRENT SCHEMA',
]);
}
protected _addLimitAndOffset(options: AddLimitOffsetOptions) {
let fragment = '';
if (options.offset) {
fragment += ` OFFSET ${this.escape(options.offset, options)} ROWS`;
}
if (options.limit != null) {
fragment += ` FETCH NEXT ${this.escape(options.limit, options)} ROWS ONLY`;
}
return fragment;
}
}