typesql-cli 0.5.18 → 0.6.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (41) hide show
  1. package/code-generator.js +2 -2
  2. package/code-generator.js.map +1 -1
  3. package/describe-query.d.ts +1 -1
  4. package/describe-query.d.ts.map +1 -1
  5. package/describe-query.js +2 -3
  6. package/describe-query.js.map +1 -1
  7. package/mysql-query-analyzer/collect-constraints.d.ts +22 -49
  8. package/mysql-query-analyzer/collect-constraints.d.ts.map +1 -1
  9. package/mysql-query-analyzer/collect-constraints.js +39 -1757
  10. package/mysql-query-analyzer/collect-constraints.js.map +1 -1
  11. package/mysql-query-analyzer/infer-column-nullability.d.ts +3 -3
  12. package/mysql-query-analyzer/infer-column-nullability.d.ts.map +1 -1
  13. package/mysql-query-analyzer/infer-column-nullability.js +8 -25
  14. package/mysql-query-analyzer/infer-column-nullability.js.map +1 -1
  15. package/mysql-query-analyzer/infer-param-nullability.d.ts +3 -1
  16. package/mysql-query-analyzer/infer-param-nullability.d.ts.map +1 -1
  17. package/mysql-query-analyzer/infer-param-nullability.js +21 -3
  18. package/mysql-query-analyzer/infer-param-nullability.js.map +1 -1
  19. package/mysql-query-analyzer/parse.d.ts +10 -10
  20. package/mysql-query-analyzer/parse.d.ts.map +1 -1
  21. package/mysql-query-analyzer/parse.js +126 -184
  22. package/mysql-query-analyzer/parse.js.map +1 -1
  23. package/mysql-query-analyzer/select-columns.d.ts +8 -9
  24. package/mysql-query-analyzer/select-columns.d.ts.map +1 -1
  25. package/mysql-query-analyzer/select-columns.js +26 -226
  26. package/mysql-query-analyzer/select-columns.js.map +1 -1
  27. package/mysql-query-analyzer/traverse.d.ts +46 -0
  28. package/mysql-query-analyzer/traverse.d.ts.map +1 -0
  29. package/mysql-query-analyzer/traverse.js +1605 -0
  30. package/mysql-query-analyzer/traverse.js.map +1 -0
  31. package/mysql-query-analyzer/types.d.ts +34 -5
  32. package/mysql-query-analyzer/types.d.ts.map +1 -1
  33. package/mysql-query-analyzer/unify.d.ts +4 -3
  34. package/mysql-query-analyzer/unify.d.ts.map +1 -1
  35. package/mysql-query-analyzer/unify.js +540 -48
  36. package/mysql-query-analyzer/unify.js.map +1 -1
  37. package/mysql-query-analyzer/verify-multiple-result.js +1 -1
  38. package/mysql-query-analyzer/verify-multiple-result.js.map +1 -1
  39. package/package.json +1 -1
  40. package/types.d.ts +2 -2
  41. package/types.d.ts.map +1 -1
@@ -0,0 +1,1605 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.verifyMultipleResult2 = exports.isMultipleRowResult = exports.selectAllColumns = exports.filterColumns = exports.traverseWithClause = exports.traverseQuerySpecification = exports.getUpdateColumns = exports.traverseDeleteStatement = exports.traverseInsertStatement = exports.traverseSql = exports.traverseQueryContext = void 0;
4
+ const ts_mysql_parser_1 = require("ts-mysql-parser");
5
+ const describe_query_1 = require("../describe-query");
6
+ const parse_1 = require("./parse");
7
+ const collect_constraints_1 = require("./collect-constraints");
8
+ const select_columns_1 = require("./select-columns");
9
+ const infer_column_nullability_1 = require("./infer-column-nullability");
10
+ const infer_param_nullability_1 = require("./infer-param-nullability");
11
+ const util_1 = require("./util");
12
+ function traverseQueryContext(queryContext, dbSchema, namedParameters) {
13
+ var _a, _b, _c, _d;
14
+ const constraints = [];
15
+ const parameters = [];
16
+ const selectStatement = (_a = queryContext.simpleStatement()) === null || _a === void 0 ? void 0 : _a.selectStatement();
17
+ if (selectStatement) {
18
+ const typeInfer = traverseSelectStatement(selectStatement, constraints, parameters, dbSchema, namedParameters);
19
+ return typeInfer;
20
+ }
21
+ const insertStatement = (_b = queryContext.simpleStatement()) === null || _b === void 0 ? void 0 : _b.insertStatement();
22
+ if (insertStatement) {
23
+ return traverseInsertStatement(insertStatement, constraints, parameters, dbSchema);
24
+ }
25
+ const updateStatement = (_c = queryContext.simpleStatement()) === null || _c === void 0 ? void 0 : _c.updateStatement();
26
+ if (updateStatement) {
27
+ const typeInfer = traverseUpdateStatement(updateStatement, constraints, parameters, dbSchema, namedParameters);
28
+ return typeInfer;
29
+ }
30
+ const deleteStatement = (_d = queryContext.simpleStatement()) === null || _d === void 0 ? void 0 : _d.deleteStatement();
31
+ if (deleteStatement) {
32
+ const typeInfer = traverseDeleteStatement(deleteStatement, constraints, parameters, dbSchema);
33
+ return typeInfer;
34
+ }
35
+ throw Error('traverseSql - not supported: ' + queryContext.constructor.name);
36
+ }
37
+ exports.traverseQueryContext = traverseQueryContext;
38
+ function traverseSql(sql, dbSchema) {
39
+ const { sql: processedSql, namedParameters } = (0, describe_query_1.preprocessSql)(sql);
40
+ const tree = (0, parse_1.parse)(processedSql);
41
+ return traverseQueryContext(tree, dbSchema, namedParameters);
42
+ }
43
+ exports.traverseSql = traverseSql;
44
+ function traverseSelectStatement(selectStatement, constraints, parameters, dbSchema, namedParameters) {
45
+ const queryExpression = selectStatement.queryExpression();
46
+ if (queryExpression) {
47
+ const withClause = queryExpression.withClause();
48
+ const withSchema = [];
49
+ if (withClause) {
50
+ traverseWithClause(withClause, constraints, parameters, dbSchema, withSchema);
51
+ }
52
+ const queryExpressionBody = queryExpression.queryExpressionBody();
53
+ if (queryExpressionBody) {
54
+ const result = traverseQueryExpressionBody(queryExpressionBody, constraints, parameters, dbSchema, withSchema, []);
55
+ const orderByParameters = (0, parse_1.extractOrderByParameters)(selectStatement);
56
+ const limitParameters = (0, parse_1.extractLimitParameters)(selectStatement);
57
+ const paramInference = (0, infer_param_nullability_1.inferParamNullabilityQueryExpression)(queryExpression);
58
+ const allParameters = parameters
59
+ .map((param, index) => {
60
+ const param2 = {
61
+ name: param.name,
62
+ type: param,
63
+ notNull: paramInference[index]
64
+ };
65
+ return param2;
66
+ });
67
+ const paramIndexes = (0, util_1.getParameterIndexes)(namedParameters.slice(0, allParameters.length)); //for [a, a, b, a] will return a: [0, 1, 3]; b: [2]
68
+ paramIndexes.forEach(paramIndex => {
69
+ (0, util_1.getPairWise)(paramIndex.indexes, (cur, next) => {
70
+ constraints.push({
71
+ expression: paramIndex.paramName,
72
+ type1: allParameters[cur].type,
73
+ type2: allParameters[next].type
74
+ });
75
+ });
76
+ });
77
+ const isMultiRow = isMultipleRowResult(selectStatement, result.fromColumns);
78
+ const traverseResult = {
79
+ type: 'Select',
80
+ constraints,
81
+ columns: result.columns,
82
+ parameters: allParameters,
83
+ limitParameters,
84
+ isMultiRow
85
+ };
86
+ const orderByColumns = orderByParameters.length > 0 ? getOrderByColumns(result.fromColumns, result.columns) : undefined;
87
+ if (orderByColumns) {
88
+ traverseResult.orderByColumns = orderByColumns;
89
+ }
90
+ return traverseResult;
91
+ }
92
+ }
93
+ throw Error('traverseSelectStatement - not supported: ' + selectStatement.text);
94
+ }
95
+ function traverseInsertStatement(insertStatement, constraints, parameters, dbSchema) {
96
+ var _a, _b;
97
+ const allParameters = [];
98
+ const paramsNullability = {};
99
+ let exprOrDefaultList = [];
100
+ const valuesContext = (_a = insertStatement.insertFromConstructor()) === null || _a === void 0 ? void 0 : _a.insertValues().valueList().values();
101
+ if (valuesContext) {
102
+ exprOrDefaultList = valuesContext.map(valueContext => { var _a; return ((_a = valueContext.children) === null || _a === void 0 ? void 0 : _a.filter(valueContext => valueContext instanceof ts_mysql_parser_1.ExprIsContext || valueContext.text == 'DEFAULT')) || []; });
103
+ }
104
+ const insertIntoTable = (0, collect_constraints_1.getInsertIntoTable)(insertStatement);
105
+ const fromColumns = dbSchema
106
+ .filter(c => c.table == insertIntoTable)
107
+ .map(c => {
108
+ const col = {
109
+ table: c.table,
110
+ columnName: c.column,
111
+ columnType: (0, collect_constraints_1.freshVar)(c.column, c.column_type),
112
+ columnKey: c.columnKey,
113
+ notNull: c.notNull
114
+ };
115
+ return col;
116
+ });
117
+ const insertColumns = (0, collect_constraints_1.getInsertColumns)(insertStatement, fromColumns);
118
+ exprOrDefaultList.forEach(exprOrDefault => {
119
+ exprOrDefault.forEach((expr, index) => {
120
+ const column = insertColumns[index];
121
+ if (expr instanceof ts_mysql_parser_1.ExprContext) {
122
+ const numberParamsBefore = parameters.length;
123
+ const exprType = traverseExpr(expr, constraints, parameters, dbSchema, [], fromColumns);
124
+ const paramNullabilityExpr = (0, infer_param_nullability_1.inferParamNullability)(expr);
125
+ parameters.slice(numberParamsBefore).forEach(param => {
126
+ paramsNullability[param.id] = paramNullabilityExpr.every(n => n) && column.notNull;
127
+ });
128
+ constraints.push({
129
+ expression: expr.text,
130
+ //TODO - CHANGING ORDER SHOULDN'T AFFECT THE TYPE INFERENCE
131
+ type1: exprType.kind == 'TypeOperator' ? exprType.types[0] : exprType,
132
+ type2: (0, collect_constraints_1.freshVar)(column.columnName, column.columnType.type)
133
+ });
134
+ }
135
+ else {
136
+ }
137
+ });
138
+ });
139
+ const updateList = ((_b = insertStatement.insertUpdateList()) === null || _b === void 0 ? void 0 : _b.updateList().updateElement()) || [];
140
+ updateList.forEach(updateElement => {
141
+ const columnName = updateElement.columnRef().text;
142
+ const field = (0, select_columns_1.splitName)(columnName);
143
+ const expr = updateElement.expr();
144
+ if (expr) {
145
+ const numberParamsBefore = parameters.length;
146
+ const exprType = traverseExpr(expr, constraints, parameters, dbSchema, /*withSchema*/ [], fromColumns);
147
+ const column = (0, select_columns_1.findColumn)(field, fromColumns);
148
+ parameters.slice(numberParamsBefore).forEach(param => {
149
+ paramsNullability[param.id] = column.notNull;
150
+ });
151
+ constraints.push({
152
+ expression: expr.text,
153
+ type1: exprType,
154
+ type2: (0, collect_constraints_1.freshVar)(column.columnName, column.columnType.type)
155
+ });
156
+ }
157
+ });
158
+ const insertQueryExpression = insertStatement.insertQueryExpression();
159
+ if (insertQueryExpression) {
160
+ //TODO - REMOVE numberParamsBefore (walk first insertQueryExpression)
161
+ const numberParamsBefore = parameters.length;
162
+ const exprTypes = traverseInsertQueryExpression(insertQueryExpression, constraints, parameters, dbSchema, /*withSchema*/ [], fromColumns);
163
+ exprTypes.columns.forEach((type, index) => {
164
+ const column = insertColumns[index];
165
+ if (type.type.kind == 'TypeVar') {
166
+ paramsNullability[type.type.id] = column.notNull;
167
+ }
168
+ constraints.push({
169
+ expression: insertQueryExpression.text,
170
+ type1: type.type,
171
+ type2: (0, collect_constraints_1.freshVar)(column.columnName, column.columnType.type)
172
+ });
173
+ });
174
+ const paramNullabilityExpr = (0, infer_param_nullability_1.inferParamNullabilityQuery)(insertQueryExpression);
175
+ parameters.slice(numberParamsBefore).forEach((param, index) => {
176
+ if (paramsNullability[param.id] == null) {
177
+ paramsNullability[param.id] = paramNullabilityExpr[index];
178
+ }
179
+ });
180
+ }
181
+ const typeInfo = (0, collect_constraints_1.generateTypeInfo)(parameters, constraints);
182
+ typeInfo.forEach((param, index) => {
183
+ const paramId = parameters[index].id;
184
+ allParameters.push({
185
+ name: 'param' + (allParameters.length + 1),
186
+ columnType: (0, describe_query_1.verifyNotInferred)(param),
187
+ notNull: paramsNullability[paramId]
188
+ });
189
+ });
190
+ const typeInferenceResult = {
191
+ type: 'Insert',
192
+ constraints: constraints,
193
+ parameters: allParameters
194
+ };
195
+ return typeInferenceResult;
196
+ }
197
+ exports.traverseInsertStatement = traverseInsertStatement;
198
+ function traverseUpdateStatement(updateStatement, constraints, parameters, dbSchema, namedParamters) {
199
+ var _a;
200
+ const updateElement = updateStatement.updateList().updateElement();
201
+ const withClause = updateStatement.withClause();
202
+ const withSchema = [];
203
+ if (withClause) {
204
+ traverseWithClause(withClause, constraints, parameters, dbSchema, withSchema);
205
+ }
206
+ const updateColumns = getUpdateColumns(updateStatement, constraints, parameters, dbSchema, withSchema, []);
207
+ const dataTypes = [];
208
+ const whereParameters = [];
209
+ const paramsBefore = parameters.length;
210
+ const whereExpr = (_a = updateStatement.whereClause()) === null || _a === void 0 ? void 0 : _a.expr();
211
+ const paramNullability = (0, infer_param_nullability_1.inferParamNullability)(updateStatement);
212
+ updateElement.forEach(updateElement => {
213
+ const expr = updateElement.expr();
214
+ if (expr) {
215
+ const result = traverseExpr(expr, constraints, parameters, dbSchema, withSchema, updateColumns);
216
+ const columnName = updateElement.columnRef().text;
217
+ const field = (0, select_columns_1.splitName)(columnName);
218
+ const column = (0, select_columns_1.findColumn)(field, updateColumns);
219
+ constraints.push({
220
+ expression: updateStatement.text,
221
+ type1: result,
222
+ type2: column.columnType //freshVar(column.columnName, )
223
+ });
224
+ parameters.slice(paramsBefore, parameters.length).forEach((param, index) => {
225
+ dataTypes.push({
226
+ name: namedParamters[paramsBefore + index] || field.name,
227
+ type: param,
228
+ notNull: column.notNull && !(0, infer_column_nullability_1.possibleNull)(field, expr)
229
+ });
230
+ });
231
+ }
232
+ });
233
+ const paramsAfter = parameters.length;
234
+ if (whereExpr) {
235
+ traverseExpr(whereExpr, constraints, parameters, dbSchema, withSchema, updateColumns);
236
+ }
237
+ parameters.slice(0, paramsBefore).forEach((param, index) => {
238
+ whereParameters.push({
239
+ name: namedParamters[index] || 'param' + (whereParameters.length + 1),
240
+ type: param,
241
+ notNull: paramNullability[index]
242
+ });
243
+ });
244
+ parameters.slice(paramsAfter).forEach((param, index) => {
245
+ whereParameters.push({
246
+ name: namedParamters[paramsAfter + index] || 'param' + (whereParameters.length + 1),
247
+ type: param,
248
+ notNull: paramNullability[paramsAfter + index]
249
+ });
250
+ });
251
+ const typeInferenceResult = {
252
+ type: 'Update',
253
+ constraints,
254
+ data: dataTypes,
255
+ parameters: whereParameters
256
+ };
257
+ return typeInferenceResult;
258
+ }
259
+ function traverseDeleteStatement(deleteStatement, constraints, parameters, dbSchema) {
260
+ var _a;
261
+ const whereExpr = (_a = deleteStatement.whereClause()) === null || _a === void 0 ? void 0 : _a.expr();
262
+ const deleteColumns = (0, collect_constraints_1.getDeleteColumns)(deleteStatement, dbSchema);
263
+ const allParameters = [];
264
+ if (whereExpr) {
265
+ traverseExpr(whereExpr, constraints, parameters, dbSchema, [], deleteColumns);
266
+ const typeInfo = (0, collect_constraints_1.generateTypeInfo)(parameters, constraints);
267
+ const paramNullability = (0, infer_param_nullability_1.inferParamNullability)(whereExpr);
268
+ typeInfo.forEach((param, paramIndex) => {
269
+ allParameters.push({
270
+ name: 'param' + (allParameters.length + 1),
271
+ columnType: (0, describe_query_1.verifyNotInferred)(param),
272
+ notNull: paramNullability[paramIndex]
273
+ });
274
+ });
275
+ }
276
+ const typeInferenceResult = {
277
+ type: 'Delete',
278
+ constraints,
279
+ parameters: allParameters
280
+ };
281
+ return typeInferenceResult;
282
+ }
283
+ exports.traverseDeleteStatement = traverseDeleteStatement;
284
+ function getUpdateColumns(updateStatement, constraints, parameters, dbSchema, withSchema, fromColumns) {
285
+ const tableReferences = updateStatement.tableReferenceList().tableReference();
286
+ const columns = traverseTableReferenceList(tableReferences, constraints, parameters, dbSchema, withSchema, fromColumns);
287
+ return columns;
288
+ }
289
+ exports.getUpdateColumns = getUpdateColumns;
290
+ function traverseInsertQueryExpression(insertQueryExpression, constraints, parameters, dbSchema, withSchema, fromColumns) {
291
+ const queryExpressionOrParens = insertQueryExpression.queryExpressionOrParens();
292
+ return traverseQueryExpressionOrParens(queryExpressionOrParens, constraints, parameters, dbSchema, withSchema, fromColumns);
293
+ }
294
+ function traverseQueryExpressionOrParens(queryExpressionOrParens, constraints, parameters, dbSchema, withSchema, fromColumns) {
295
+ const queryExpression = queryExpressionOrParens.queryExpression();
296
+ if (queryExpression) {
297
+ return traverseQueryExpression(queryExpression, constraints, parameters, dbSchema, withSchema, fromColumns);
298
+ }
299
+ const queryEpressionParens = queryExpressionOrParens.queryExpressionParens();
300
+ if (queryEpressionParens) {
301
+ return traverseQueryExpressionParens(queryEpressionParens, constraints, parameters, dbSchema, withSchema, fromColumns);
302
+ }
303
+ throw Error("walkQueryExpressionOrParens");
304
+ }
305
+ function traverseQueryExpression(queryExpression, constraints, parameters, dbSchema, withSchema, fromColumns, recursive = false) {
306
+ const queryExpressionBody = queryExpression.queryExpressionBody();
307
+ if (queryExpressionBody) {
308
+ return traverseQueryExpressionBody(queryExpressionBody, constraints, parameters, dbSchema, withSchema, fromColumns);
309
+ }
310
+ const queryExpressionParens = queryExpression.queryExpressionParens();
311
+ if (queryExpressionParens) {
312
+ return traverseQueryExpressionParens(queryExpressionParens, constraints, parameters, dbSchema, withSchema, fromColumns, recursive);
313
+ }
314
+ throw Error("walkQueryExpression");
315
+ }
316
+ function traverseQueryExpressionParens(queryExpressionParens, constraints, parameters, dbSchema, withSchema, fromColumns, recursive = false) {
317
+ const queryExpression = queryExpressionParens.queryExpression();
318
+ if (queryExpression) {
319
+ return traverseQueryExpression(queryExpression, constraints, parameters, dbSchema, withSchema, fromColumns, recursive);
320
+ }
321
+ const queryExpressionParens2 = queryExpressionParens.queryExpressionParens();
322
+ if (queryExpressionParens2) {
323
+ return traverseQueryExpressionParens(queryExpressionParens, constraints, parameters, dbSchema, withSchema, fromColumns, recursive);
324
+ }
325
+ throw Error("walkQueryExpressionParens");
326
+ }
327
+ function traverseQueryExpressionBody(queryExpressionBody, constraints, parameters, dbSchema, withSchema, fromColumns, recursiveNames) {
328
+ const subQuery = queryExpressionBody instanceof ts_mysql_parser_1.SubqueryContext ? true : false;
329
+ const allQueries = (0, parse_1.getAllQuerySpecificationsFromSelectStatement)(queryExpressionBody);
330
+ const [first, ...unionQuerySpec] = allQueries;
331
+ const mainQueryResult = traverseQuerySpecification(first, constraints, parameters, dbSchema, withSchema, fromColumns, subQuery);
332
+ const resultTypes = mainQueryResult.columns.map((t, index) => unionQuerySpec.length == 0 ? t.type : (0, collect_constraints_1.freshVar)(recursiveNames && recursiveNames.length > 0 ? recursiveNames[index] : t.name, t.type.type)); //TODO mover para traversequeryspecificat?
333
+ for (let queryIndex = 0; queryIndex < unionQuerySpec.length; queryIndex++) {
334
+ const columnNames = recursiveNames && recursiveNames.length > 0 ? recursiveNames : mainQueryResult.columns.map(col => col.name);
335
+ const newFromColumns = recursiveNames ? renameFromColumns(mainQueryResult.columns, columnNames) : mainQueryResult.fromColumns;
336
+ const unionQuery = unionQuerySpec[queryIndex];
337
+ const unionResult = traverseQuerySpecification(unionQuery, constraints, parameters, dbSchema, withSchema, newFromColumns, subQuery);
338
+ resultTypes.forEach((t2, index) => {
339
+ mainQueryResult.columns[index].notNull = mainQueryResult.columns[index].notNull && unionResult.columns[index].notNull;
340
+ constraints.push({
341
+ expression: 'union',
342
+ coercionType: 'Union',
343
+ mostGeneralType: true,
344
+ type1: t2,
345
+ type2: unionResult.columns[index].type
346
+ });
347
+ });
348
+ }
349
+ const resultTypeAndNotNull = resultTypes.map((c, index) => {
350
+ const col = {
351
+ name: resultTypes[index].name,
352
+ type: resultTypes[index],
353
+ notNull: mainQueryResult.columns[index].notNull,
354
+ };
355
+ return col;
356
+ });
357
+ const result = {
358
+ columns: resultTypeAndNotNull,
359
+ fromColumns: mainQueryResult.fromColumns
360
+ };
361
+ return result;
362
+ }
363
+ function renameFromColumns(fromColumns, recursiveNames) {
364
+ const newFromColumns = fromColumns.map((col, index) => {
365
+ const newCol = {
366
+ table: "",
367
+ columnName: recursiveNames[index],
368
+ columnType: col.type,
369
+ columnKey: "",
370
+ notNull: col.notNull
371
+ };
372
+ return newCol;
373
+ });
374
+ return newFromColumns;
375
+ }
376
+ function traverseQuerySpecification(querySpec, constraints, parameters, dbSchema, withSchema, fromColumnsParent, subQuery = false) {
377
+ const fromClause = querySpec.fromClause();
378
+ const fromColumns = fromClause ? traverseFromClause(fromClause, constraints, parameters, dbSchema, withSchema, fromColumnsParent) : [];
379
+ const allColumns = subQuery ? fromColumnsParent.concat(fromColumns) : fromColumns; //(... where id = t1.id)
380
+ const selectItemListResult = traverseSelectItemList(querySpec.selectItemList(), constraints, parameters, dbSchema, withSchema, allColumns);
381
+ const whereClause = querySpec.whereClause();
382
+ //TODO - HAVING, BLAH
383
+ if (whereClause) {
384
+ const whereExpr = whereClause === null || whereClause === void 0 ? void 0 : whereClause.expr();
385
+ traverseExpr(whereExpr, constraints, parameters, dbSchema, withSchema, allColumns);
386
+ }
387
+ const columnNullability = (0, infer_column_nullability_1.inferNotNull)(querySpec, dbSchema, allColumns);
388
+ const columns = selectItemListResult.types.map((t, index) => {
389
+ const t2 = t;
390
+ const resultType = {
391
+ name: t2.name,
392
+ type: t2,
393
+ notNull: columnNullability[index]
394
+ };
395
+ return resultType;
396
+ });
397
+ const havingClause = querySpec.havingClause();
398
+ if (havingClause) {
399
+ const selectColumns = columns.map(c => {
400
+ const col = {
401
+ table: "",
402
+ columnName: c.name,
403
+ columnType: c.type,
404
+ columnKey: "",
405
+ notNull: c.notNull
406
+ };
407
+ return col;
408
+ });
409
+ traverseHavingClause(havingClause, constraints, parameters, dbSchema, withSchema, selectColumns.concat(fromColumns));
410
+ }
411
+ return {
412
+ columns,
413
+ fromColumns
414
+ };
415
+ }
416
+ exports.traverseQuerySpecification = traverseQuerySpecification;
417
+ function traverseWithClause(withClause, constraints, parameters, dbSchema, withSchema) {
418
+ //result1, result2
419
+ withClause.commonTableExpression().forEach(commonTableExpression => {
420
+ var _a;
421
+ const identifier = commonTableExpression.identifier().text;
422
+ const recursiveNames = withClause.RECURSIVE_SYMBOL() ? ((_a = commonTableExpression.columnInternalRefList()) === null || _a === void 0 ? void 0 : _a.columnInternalRef().map(t => t.text)) || [] : undefined;
423
+ const subQuery = commonTableExpression.subquery();
424
+ const subqueryResult = traverseSubquery(subQuery, constraints, parameters, dbSchema, withSchema, [], recursiveNames); //recursive= true??
425
+ subqueryResult.columns.forEach(col => {
426
+ const withCol = {
427
+ table: identifier,
428
+ columnName: col.name,
429
+ columnType: col.type,
430
+ columnKey: "",
431
+ notNull: col.notNull
432
+ };
433
+ withSchema.push(withCol);
434
+ });
435
+ });
436
+ }
437
+ exports.traverseWithClause = traverseWithClause;
438
+ function traverseFromClause(fromClause, constraints, parameters, dbSchema, withSchema, fromColumnsParent) {
439
+ var _a;
440
+ const tableReferenceList = (_a = fromClause.tableReferenceList()) === null || _a === void 0 ? void 0 : _a.tableReference();
441
+ const fromColumns = tableReferenceList ? traverseTableReferenceList(tableReferenceList, constraints, parameters, dbSchema, withSchema, fromColumnsParent) : [];
442
+ return fromColumns;
443
+ }
444
+ function traverseTableReferenceList(tableReferenceList, constraints, parameters, dbSchema, withSchema, fromColumns) {
445
+ const result = [];
446
+ tableReferenceList.forEach(tab => {
447
+ const tableFactor = tab.tableFactor();
448
+ if (tableFactor) {
449
+ const fields = traverseTableFactor(tableFactor, constraints, parameters, dbSchema, withSchema, fromColumns);
450
+ result.push(...fields);
451
+ }
452
+ const allJoinedColumns = [];
453
+ let firstLeftJoinIndex = -1;
454
+ tab.joinedTable().forEach((joined, index) => {
455
+ var _a, _b;
456
+ if (((_a = joined.innerJoinType()) === null || _a === void 0 ? void 0 : _a.INNER_SYMBOL()) || ((_b = joined.innerJoinType()) === null || _b === void 0 ? void 0 : _b.JOIN_SYMBOL())) {
457
+ firstLeftJoinIndex = -1; //dont need to add notNull = false to joins
458
+ }
459
+ else if (firstLeftJoinIndex == -1) {
460
+ firstLeftJoinIndex = index; //add notNull = false to all joins after the first left join
461
+ }
462
+ const tableReferences = joined.tableReference();
463
+ if (tableReferences) {
464
+ const usingFields = (0, select_columns_1.extractFieldsFromUsingClause)(joined);
465
+ const joinedFields = traverseTableReferenceList([tableReferences], constraints, parameters, dbSchema, withSchema, fromColumns);
466
+ //doesn't duplicate the fields of the USING clause. Ex. INNER JOIN mytable2 USING(id);
467
+ const joinedFieldsFiltered = usingFields.length > 0 ? filterUsingFields(joinedFields, usingFields) : joinedFields;
468
+ allJoinedColumns.push(joinedFieldsFiltered);
469
+ const onClause = joined.expr(); //ON expr
470
+ if (onClause) {
471
+ joinedFieldsFiltered.forEach(field => {
472
+ const fieldName = {
473
+ name: field.columnName,
474
+ prefix: field.tableAlias || ''
475
+ };
476
+ field.notNull = field.notNull || !(0, infer_column_nullability_1.possibleNull)(fieldName, onClause);
477
+ });
478
+ //apply inference to the parent join too
479
+ result.forEach(field => {
480
+ const fieldName = {
481
+ name: field.columnName,
482
+ prefix: field.tableAlias || ''
483
+ };
484
+ field.notNull = field.notNull || !(0, infer_column_nullability_1.possibleNull)(fieldName, onClause);
485
+ });
486
+ traverseExpr(onClause, constraints, parameters, dbSchema, withSchema, allJoinedColumns.flatMap(c => c).concat(result));
487
+ }
488
+ }
489
+ });
490
+ allJoinedColumns.forEach((joinedColumns, index) => {
491
+ joinedColumns.forEach(field => {
492
+ if (firstLeftJoinIndex != -1 && index >= firstLeftJoinIndex) {
493
+ const newField = Object.assign(Object.assign({}, field), { notNull: false });
494
+ result.push(newField);
495
+ }
496
+ else {
497
+ result.push(field);
498
+ }
499
+ });
500
+ });
501
+ });
502
+ return result;
503
+ }
504
+ function traverseTableFactor(tableFactor, constraints, parameters, dbSchema, withSchema, fromColumns) {
505
+ var _a;
506
+ const singleTable = tableFactor.singleTable();
507
+ if (singleTable) {
508
+ return traverseSingleTable(singleTable, constraints, parameters, dbSchema, withSchema);
509
+ }
510
+ const derivadTable = tableFactor.derivedTable();
511
+ if (derivadTable) {
512
+ const tableAlias = (_a = derivadTable.tableAlias()) === null || _a === void 0 ? void 0 : _a.identifier().text;
513
+ const subQuery = derivadTable.subquery();
514
+ if (subQuery) {
515
+ const subQueryResult = traverseSubquery(subQuery, constraints, parameters, dbSchema, withSchema, fromColumns);
516
+ const result = subQueryResult.columns.map(t => {
517
+ const colDef = {
518
+ table: "",
519
+ columnName: t.name,
520
+ columnType: t.type,
521
+ columnKey: "",
522
+ notNull: t.notNull,
523
+ tableAlias: tableAlias
524
+ };
525
+ return colDef;
526
+ });
527
+ return result;
528
+ }
529
+ }
530
+ const tableReferenceListParens = tableFactor.tableReferenceListParens();
531
+ if (tableReferenceListParens) {
532
+ const listParens = traverseTableReferenceListParens(tableReferenceListParens, constraints, parameters, dbSchema, withSchema, fromColumns);
533
+ return listParens;
534
+ }
535
+ throw Error('traverseTableFactor - not supported: ' + tableFactor.constructor.name);
536
+ }
537
+ //tableReferenceList | tableReferenceListParens
538
+ function traverseTableReferenceListParens(ctx, constraints, parameters, dbSchema, withSchema, fromColumns) {
539
+ const tableReferenceList = ctx.tableReferenceList();
540
+ if (tableReferenceList) {
541
+ return traverseTableReferenceList(tableReferenceList.tableReference(), constraints, parameters, dbSchema, withSchema, fromColumns);
542
+ }
543
+ const tableReferenceListParens = ctx.tableReferenceListParens();
544
+ if (tableReferenceListParens) {
545
+ return traverseTableReferenceListParens(tableReferenceListParens, constraints, parameters, dbSchema, withSchema, fromColumns);
546
+ }
547
+ throw Error('traverseTableReferenceListParens - not supported: ' + ctx.constructor.name);
548
+ }
549
+ function traverseSingleTable(singleTable, constraints, parameters, dbSchema, withSchema) {
550
+ var _a;
551
+ const table = singleTable === null || singleTable === void 0 ? void 0 : singleTable.tableRef().text;
552
+ const tableAlias = (_a = singleTable === null || singleTable === void 0 ? void 0 : singleTable.tableAlias()) === null || _a === void 0 ? void 0 : _a.identifier().text;
553
+ const tableName = (0, select_columns_1.splitName)(table);
554
+ const fields = filterColumns(dbSchema, withSchema, tableAlias, tableName);
555
+ return fields;
556
+ }
557
+ function traverseSubquery(subQuery, constraints, parameters, dbSchema, fromColumns, withSchema, recursiveNames) {
558
+ const result = traverseQueryExpressionBody(subQuery, constraints, parameters, dbSchema, fromColumns, withSchema, recursiveNames);
559
+ return result;
560
+ }
561
+ function traverseSelectItemList(selectItemList, constraints, parameters, dbSchema, withSchema, fromColumns) {
562
+ const listType = [];
563
+ if (selectItemList.MULT_OPERATOR()) {
564
+ fromColumns.forEach(col => {
565
+ const columnType = (0, collect_constraints_1.createColumnType)(col);
566
+ listType.push(columnType);
567
+ });
568
+ }
569
+ selectItemList.selectItem().forEach(selectItem => {
570
+ const tableWild = selectItem.tableWild();
571
+ if (tableWild) {
572
+ if (tableWild.MULT_OPERATOR()) {
573
+ const itemName = (0, select_columns_1.splitName)(selectItem.text);
574
+ const allColumns = selectAllColumns(itemName.prefix, fromColumns);
575
+ allColumns.forEach(col => {
576
+ listType.push((0, collect_constraints_1.createColumnType)(col));
577
+ });
578
+ }
579
+ }
580
+ const expr = selectItem.expr();
581
+ if (expr) {
582
+ const exprType = traverseExpr(expr, constraints, parameters, dbSchema, withSchema, fromColumns);
583
+ if (exprType.kind == 'TypeOperator') {
584
+ const subqueryType = exprType.types[0];
585
+ subqueryType.name = (0, select_columns_1.getColumnName)(selectItem);
586
+ listType.push(subqueryType);
587
+ }
588
+ else if (exprType.kind == 'TypeVar') {
589
+ exprType.name = (0, select_columns_1.getColumnName)(selectItem);
590
+ listType.push(Object.assign({}, exprType)); //clone
591
+ }
592
+ }
593
+ });
594
+ const result = {
595
+ kind: 'TypeOperator',
596
+ types: listType
597
+ };
598
+ return result;
599
+ }
600
+ function traverseHavingClause(havingClause, constraints, parameters, dbSchema, withSchema, fromColumns) {
601
+ const havingExpr = havingClause.expr();
602
+ traverseExpr(havingExpr, constraints, parameters, dbSchema, withSchema, fromColumns);
603
+ }
604
+ function traverseExpr(expr, constraints, parameters, dbSchema, withSchema, fromColumns) {
605
+ if (expr instanceof ts_mysql_parser_1.ExprIsContext) {
606
+ const boolPri = expr.boolPri();
607
+ const boolPriType = traverseBoolPri(boolPri, constraints, parameters, dbSchema, withSchema, fromColumns);
608
+ return boolPriType;
609
+ }
610
+ if (expr instanceof ts_mysql_parser_1.ExprNotContext) {
611
+ return (0, collect_constraints_1.freshVar)(expr.text, 'tinyint');
612
+ ;
613
+ }
614
+ if (expr instanceof ts_mysql_parser_1.ExprAndContext || expr instanceof ts_mysql_parser_1.ExprXorContext || expr instanceof ts_mysql_parser_1.ExprOrContext) {
615
+ const exprLeft = expr.expr()[0];
616
+ traverseExpr(exprLeft, constraints, parameters, dbSchema, withSchema, fromColumns);
617
+ const exprRight = expr.expr()[1];
618
+ traverseExpr(exprRight, constraints, parameters, dbSchema, withSchema, fromColumns);
619
+ return (0, collect_constraints_1.freshVar)(expr.text, 'tinyint');
620
+ }
621
+ throw Error('traverseExpr - not supported: ' + expr.text);
622
+ }
623
+ function traverseBoolPri(boolPri, constraints, parameters, dbSchema, withSchema, fromColumns) {
624
+ if (boolPri instanceof ts_mysql_parser_1.PrimaryExprPredicateContext) {
625
+ const predicate = boolPri.predicate();
626
+ const predicateType = traversePredicate(predicate, constraints, parameters, dbSchema, withSchema, fromColumns);
627
+ return predicateType;
628
+ }
629
+ if (boolPri instanceof ts_mysql_parser_1.PrimaryExprIsNullContext) {
630
+ const boolPri2 = boolPri.boolPri();
631
+ traverseBoolPri(boolPri2, constraints, parameters, dbSchema, withSchema, fromColumns);
632
+ return (0, collect_constraints_1.freshVar)(boolPri.text, '?');
633
+ }
634
+ if (boolPri instanceof ts_mysql_parser_1.PrimaryExprCompareContext) {
635
+ const compareLeft = boolPri.boolPri();
636
+ const compareRight = boolPri.predicate();
637
+ const typeLeft = traverseBoolPri(compareLeft, constraints, parameters, dbSchema, withSchema, fromColumns);
638
+ const typeRight = traversePredicate(compareRight, constraints, parameters, dbSchema, withSchema, fromColumns);
639
+ constraints.push({
640
+ expression: boolPri.text,
641
+ type1: typeLeft,
642
+ type2: typeRight
643
+ });
644
+ return (0, collect_constraints_1.freshVar)(boolPri.text, 'tinyint');
645
+ }
646
+ if (boolPri instanceof ts_mysql_parser_1.PrimaryExprAllAnyContext) {
647
+ const compareLeft = boolPri.boolPri();
648
+ const compareRight = boolPri.subquery();
649
+ const typeLeft = traverseBoolPri(compareLeft, constraints, parameters, dbSchema, withSchema, fromColumns);
650
+ const subQueryResult = traverseSubquery(compareRight, constraints, parameters, dbSchema, withSchema, fromColumns);
651
+ constraints.push({
652
+ expression: boolPri.text,
653
+ type1: typeLeft,
654
+ type2: {
655
+ kind: 'TypeOperator',
656
+ types: subQueryResult.columns.map(t => t.type)
657
+ }
658
+ });
659
+ return (0, collect_constraints_1.freshVar)(boolPri.text, 'tinyint');
660
+ }
661
+ throw Error('traverseExpr - not supported: ' + boolPri.constructor.name);
662
+ }
663
+ function traversePredicate(predicate, constraints, parameters, dbSchema, withSchema, fromColumns) {
664
+ const bitExpr = predicate.bitExpr()[0]; //TODO - predicate length = 2? [1] == predicateOperations
665
+ const bitExprType = traverseBitExpr(bitExpr, constraints, parameters, dbSchema, withSchema, fromColumns);
666
+ const predicateOperations = predicate.predicateOperations();
667
+ if (predicateOperations) {
668
+ const rightType = traversePredicateOperations(predicateOperations, bitExprType, constraints, parameters, fromColumns, dbSchema, withSchema);
669
+ if (bitExprType.kind == 'TypeOperator' && rightType.kind == 'TypeOperator') {
670
+ rightType.types.forEach((t, i) => {
671
+ constraints.push({
672
+ expression: predicateOperations.text,
673
+ type1: t,
674
+ type2: bitExprType.types[i],
675
+ mostGeneralType: true
676
+ });
677
+ });
678
+ }
679
+ if (bitExprType.kind == 'TypeVar' && rightType.kind == 'TypeOperator') {
680
+ rightType.types.forEach((t, i) => {
681
+ constraints.push({
682
+ expression: predicateOperations.text,
683
+ type1: bitExprType,
684
+ type2: Object.assign(Object.assign({}, t), { list: true }),
685
+ mostGeneralType: true
686
+ });
687
+ });
688
+ // return rightType.types[0];
689
+ }
690
+ return bitExprType;
691
+ }
692
+ return bitExprType;
693
+ }
694
+ function traverseExprList(exprList, constraints, parameters, dbSchema, withSchema, fromColumns) {
695
+ const listType = exprList.expr().map(item => {
696
+ const exprType = traverseExpr(item, constraints, parameters, dbSchema, withSchema, fromColumns);
697
+ return exprType;
698
+ });
699
+ const type = {
700
+ kind: 'TypeOperator',
701
+ types: listType
702
+ };
703
+ return type;
704
+ }
705
+ function traverseBitExpr(bitExpr, constraints, parameters, dbSchema, withSchema, fromColumns) {
706
+ const simpleExpr = bitExpr.simpleExpr();
707
+ if (simpleExpr) {
708
+ return traverseSimpleExpr(simpleExpr, constraints, parameters, dbSchema, withSchema, fromColumns);
709
+ }
710
+ if (bitExpr.bitExpr().length == 2) {
711
+ const bitExprType = (0, collect_constraints_1.freshVar)(bitExpr.text, '?');
712
+ const bitExprLeft = bitExpr.bitExpr()[0];
713
+ const typeLeftTemp = traverseBitExpr(bitExprLeft, constraints, parameters, dbSchema, withSchema, fromColumns);
714
+ const typeLeft = typeLeftTemp.kind == 'TypeOperator' ? typeLeftTemp.types[0] : typeLeftTemp;
715
+ //const newTypeLeft = typeLeft.name == '?'? freshVar('?', 'bigint') : typeLeft;
716
+ const bitExprRight = bitExpr.bitExpr()[1];
717
+ const typeRightTemp = traverseBitExpr(bitExprRight, constraints, parameters, dbSchema, withSchema, fromColumns);
718
+ //In the expression 'id + (value + 2) + ?' the '(value+2)' is treated as a SimpleExprListContext and return a TypeOperator
719
+ const typeRight = typeRightTemp.kind == 'TypeOperator' ? typeRightTemp.types[0] : typeRightTemp;
720
+ //const newTypeRight = typeRight.name == '?'? freshVar('?', 'bigint') : typeRight;
721
+ //PRECISA?
722
+ // constraints.push({
723
+ // expression: bitExpr.text,
724
+ // type1: typeLeft,
725
+ // type2: typeRight,
726
+ // mostGeneralType: true,
727
+ // coercionType: 'Sum'
728
+ // })
729
+ // constraints.push({
730
+ // expression: bitExpr.text,
731
+ // type1: typeLeft,
732
+ // type2: typeRight,
733
+ // mostGeneralType: true,
734
+ // coercionType: 'Sum'
735
+ // })
736
+ // constraints.push({
737
+ // expression: bitExpr.text,
738
+ // type1: bitExprType,
739
+ // type2: typeRight,
740
+ // mostGeneralType: true,
741
+ // coercionType: 'Sum'
742
+ // })
743
+ constraints.push({
744
+ expression: bitExprLeft.text,
745
+ type1: bitExprType,
746
+ type2: typeLeft,
747
+ mostGeneralType: true,
748
+ coercionType: 'Sum'
749
+ });
750
+ constraints.push({
751
+ expression: bitExprRight.text,
752
+ type1: bitExprType,
753
+ type2: typeRight,
754
+ mostGeneralType: true,
755
+ coercionType: 'Sum'
756
+ });
757
+ // const resultType = freshVar(bitExprRight.text, 'number');
758
+ // constraints.push({
759
+ // expression: bitExprRight.text,
760
+ // type1: resultType,
761
+ // type2: freshVar(bitExprRight.text, 'number'),
762
+ // mostGeneralType: true,
763
+ // coercionType: 'Sum'
764
+ // })
765
+ return bitExprType;
766
+ }
767
+ if (bitExpr.INTERVAL_SYMBOL()) {
768
+ const bitExpr2 = bitExpr.bitExpr()[0];
769
+ const leftType = traverseBitExpr(bitExpr2, constraints, parameters, dbSchema, withSchema, fromColumns);
770
+ const expr = bitExpr.expr(); //expr interval
771
+ traverseExpr(expr, constraints, parameters, dbSchema, withSchema, fromColumns);
772
+ constraints.push({
773
+ expression: bitExpr.text,
774
+ type1: leftType,
775
+ type2: (0, collect_constraints_1.freshVar)('datetime', 'datetime')
776
+ });
777
+ return (0, collect_constraints_1.freshVar)('datetime', 'datetime');
778
+ }
779
+ throw Error('traverseBitExpr - not supported: ' + bitExpr.constructor.name);
780
+ }
781
+ function traversePredicateOperations(predicateOperations, parentType, constraints, parameters, fromColumns, dbSchema, withSchema) {
782
+ if (predicateOperations instanceof ts_mysql_parser_1.PredicateExprInContext) {
783
+ const subquery = predicateOperations.subquery();
784
+ if (subquery) {
785
+ const subQueryResult = traverseSubquery(subquery, constraints, parameters, dbSchema, withSchema, fromColumns);
786
+ return { kind: 'TypeOperator', types: subQueryResult.columns.map(t => t.type) };
787
+ }
788
+ const exprList = predicateOperations.exprList();
789
+ if (exprList) {
790
+ const rightType = traverseExprList(exprList, constraints, parameters, dbSchema, withSchema, fromColumns);
791
+ return rightType;
792
+ }
793
+ }
794
+ if (predicateOperations instanceof ts_mysql_parser_1.PredicateExprLikeContext) {
795
+ const simpleExpr = predicateOperations.simpleExpr()[0];
796
+ const rightType = traverseSimpleExpr(simpleExpr, constraints, parameters, dbSchema, withSchema, fromColumns);
797
+ constraints.push({
798
+ expression: simpleExpr.text,
799
+ type1: parentType,
800
+ type2: rightType
801
+ });
802
+ return rightType;
803
+ }
804
+ throw Error("Not expected");
805
+ }
806
+ function traverseSimpleExpr(simpleExpr, constraints, parameters, dbSchema, withSchema, fromColumns) {
807
+ var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q;
808
+ if (simpleExpr instanceof ts_mysql_parser_1.SimpleExprColumnRefContext) {
809
+ const fieldName = (0, select_columns_1.splitName)(simpleExpr.text);
810
+ const column = (0, select_columns_1.findColumn)(fieldName, fromColumns.concat(withSchema));
811
+ const typeVar = (0, collect_constraints_1.freshVar)(column.columnName, column.columnType.type);
812
+ constraints.push({
813
+ expression: simpleExpr.text,
814
+ type1: typeVar,
815
+ type2: column.columnType,
816
+ mostGeneralType: true
817
+ });
818
+ return typeVar;
819
+ }
820
+ if (simpleExpr instanceof ts_mysql_parser_1.SimpleExprParamMarkerContext) {
821
+ const param = (0, collect_constraints_1.freshVar)('?', '?');
822
+ parameters.push(param);
823
+ return param;
824
+ }
825
+ if (simpleExpr instanceof ts_mysql_parser_1.SimpleExprLiteralContext) {
826
+ const literal = simpleExpr.literal();
827
+ if (literal.textLiteral()) {
828
+ const text = ((_a = literal.textLiteral()) === null || _a === void 0 ? void 0 : _a.text.slice(1, -1)) || ''; //remove quotes
829
+ return (0, collect_constraints_1.freshVar)(text, 'varchar');
830
+ }
831
+ const numLiteral = literal.numLiteral();
832
+ if (numLiteral) {
833
+ return (0, collect_constraints_1.freshVar)(numLiteral.text, 'int');
834
+ // addNamedNode(simpleExpr, freshVar('bigint', 'bigint'), namedNodes)
835
+ // if(numLiteral.INT_NUMBER()) {
836
+ // const typeInt = freshVar('int', 'int');
837
+ // addNamedNode(simpleExpr, typeInt, namedNodes)
838
+ // }
839
+ // if(numLiteral.DECIMAL_NUMBER()) {
840
+ // const typeDecimal = freshVar('decimal', 'decimal');
841
+ // addNamedNode(simpleExpr, typeDecimal, namedNodes)
842
+ // }
843
+ // if(numLiteral.FLOAT_NUMBER()) {
844
+ // const typeFloat = freshVar('float', 'float');
845
+ // addNamedNode(simpleExpr, typeFloat, namedNodes)
846
+ // }
847
+ ;
848
+ }
849
+ const boolLiteral = literal.boolLiteral();
850
+ if (boolLiteral) {
851
+ return (0, collect_constraints_1.freshVar)(boolLiteral.text, 'bit');
852
+ }
853
+ const nullLiteral = literal.nullLiteral();
854
+ if (nullLiteral) {
855
+ return (0, collect_constraints_1.freshVar)(nullLiteral.text, '?');
856
+ }
857
+ throw Error('literal not supported:' + literal.text);
858
+ //...
859
+ }
860
+ if (simpleExpr instanceof ts_mysql_parser_1.SimpleExprListContext) {
861
+ const exprList = simpleExpr.exprList();
862
+ const listType = exprList.expr().map(item => {
863
+ const exprType = traverseExpr(item, constraints, parameters, dbSchema, withSchema, fromColumns);
864
+ return exprType;
865
+ });
866
+ const resultType = {
867
+ kind: 'TypeOperator',
868
+ types: listType
869
+ };
870
+ return resultType;
871
+ }
872
+ if (simpleExpr instanceof ts_mysql_parser_1.SimpleExprSubQueryContext) {
873
+ const subquery = simpleExpr.subquery();
874
+ const subqueryResult = traverseSubquery(subquery, constraints, parameters, dbSchema, withSchema, fromColumns);
875
+ return {
876
+ kind: 'TypeOperator',
877
+ types: subqueryResult.columns.map(t => t.type)
878
+ };
879
+ }
880
+ if (simpleExpr instanceof ts_mysql_parser_1.SimpleExprCaseContext) {
881
+ //case when expr then expr else expr
882
+ const caseType = (0, collect_constraints_1.freshVar)(simpleExpr.text, '?');
883
+ simpleExpr.whenExpression().forEach(whenExprCont => {
884
+ const whenExpr = whenExprCont.expr();
885
+ const whenType = traverseExpr(whenExpr, constraints, parameters, dbSchema, withSchema, fromColumns);
886
+ constraints.push({
887
+ expression: whenExpr.text,
888
+ type1: whenType.kind == 'TypeOperator' ? whenType.types[0] : whenType,
889
+ type2: (0, collect_constraints_1.freshVar)('tinyint', 'tinyint') //bool
890
+ });
891
+ });
892
+ const thenTypes = simpleExpr.thenExpression().map(thenExprCtx => {
893
+ const thenExpr = thenExprCtx.expr();
894
+ const thenType = traverseExpr(thenExpr, constraints, parameters, dbSchema, withSchema, fromColumns);
895
+ constraints.push({
896
+ expression: thenExprCtx.text,
897
+ type1: caseType,
898
+ type2: thenType.kind == 'TypeOperator' ? thenType.types[0] : thenType,
899
+ mostGeneralType: true,
900
+ });
901
+ return thenType;
902
+ });
903
+ const elseExpr = (_b = simpleExpr.elseExpression()) === null || _b === void 0 ? void 0 : _b.expr();
904
+ if (elseExpr) {
905
+ const elseType = traverseExpr(elseExpr, constraints, parameters, dbSchema, withSchema, fromColumns);
906
+ constraints.push({
907
+ expression: (_c = simpleExpr.elseExpression()) === null || _c === void 0 ? void 0 : _c.text,
908
+ type1: caseType,
909
+ type2: elseType.kind == 'TypeOperator' ? elseType.types[0] : elseType,
910
+ mostGeneralType: true
911
+ });
912
+ thenTypes.forEach(thenType => {
913
+ var _a;
914
+ constraints.push({
915
+ expression: (_a = simpleExpr.elseExpression()) === null || _a === void 0 ? void 0 : _a.text,
916
+ type1: thenType,
917
+ type2: elseType.kind == 'TypeOperator' ? elseType.types[0] : elseType,
918
+ mostGeneralType: true
919
+ });
920
+ });
921
+ }
922
+ return caseType;
923
+ }
924
+ if (simpleExpr instanceof ts_mysql_parser_1.SimpleExprIntervalContext) {
925
+ const exprList = simpleExpr.expr();
926
+ const exprLeft = exprList[0];
927
+ const exprRight = exprList[1];
928
+ const typeLeft = traverseExpr(exprLeft, constraints, parameters, dbSchema, withSchema, fromColumns);
929
+ const typeRight = traverseExpr(exprRight, constraints, parameters, dbSchema, withSchema, fromColumns);
930
+ constraints.push({
931
+ expression: exprLeft.text,
932
+ type1: typeLeft,
933
+ type2: (0, collect_constraints_1.freshVar)('bigint', 'bigint')
934
+ });
935
+ if (typeRight.kind == 'TypeVar' && ((0, collect_constraints_1.isDateLiteral)(typeRight.name) || (0, collect_constraints_1.isDateTimeLiteral)(typeRight.name))) {
936
+ typeRight.type = 'datetime';
937
+ }
938
+ constraints.push({
939
+ expression: exprRight.text,
940
+ type1: typeRight,
941
+ type2: (0, collect_constraints_1.freshVar)('datetime', 'datetime')
942
+ });
943
+ return (0, collect_constraints_1.freshVar)('datetime', 'datetime');
944
+ }
945
+ if (simpleExpr instanceof ts_mysql_parser_1.SimpleExprSumContext) {
946
+ const sumExpr = simpleExpr.sumExpr();
947
+ if (sumExpr.MAX_SYMBOL() || sumExpr.MIN_SYMBOL()) {
948
+ const functionType = (0, collect_constraints_1.freshVar)(simpleExpr.text, '?');
949
+ const inSumExpr = (_d = sumExpr.inSumExpr()) === null || _d === void 0 ? void 0 : _d.expr();
950
+ if (inSumExpr) {
951
+ const inSumExprType = traverseExpr(inSumExpr, constraints, parameters, dbSchema, withSchema, fromColumns);
952
+ constraints.push({
953
+ expression: simpleExpr.text,
954
+ type1: functionType,
955
+ type2: inSumExprType,
956
+ mostGeneralType: true
957
+ });
958
+ }
959
+ return functionType;
960
+ }
961
+ if (sumExpr.COUNT_SYMBOL()) {
962
+ const functionType = (0, collect_constraints_1.freshVar)(simpleExpr.text, 'bigint');
963
+ const inSumExpr = (_e = sumExpr.inSumExpr()) === null || _e === void 0 ? void 0 : _e.expr();
964
+ if (inSumExpr) {
965
+ traverseExpr(inSumExpr, constraints, parameters, dbSchema, withSchema, fromColumns);
966
+ }
967
+ return functionType;
968
+ }
969
+ if (sumExpr.SUM_SYMBOL() || sumExpr.AVG_SYMBOL()) {
970
+ const functionType = (0, collect_constraints_1.freshVar)(simpleExpr.text, '?');
971
+ const inSumExpr = (_f = sumExpr.inSumExpr()) === null || _f === void 0 ? void 0 : _f.expr();
972
+ if (inSumExpr) {
973
+ const inSumExprType = traverseExpr(inSumExpr, constraints, parameters, dbSchema, withSchema, fromColumns);
974
+ constraints.push({
975
+ expression: simpleExpr.text,
976
+ type1: functionType,
977
+ type2: inSumExprType,
978
+ mostGeneralType: true,
979
+ coercionType: 'SumFunction'
980
+ });
981
+ }
982
+ return functionType;
983
+ }
984
+ if (sumExpr.GROUP_CONCAT_SYMBOL()) {
985
+ const exprList = sumExpr.exprList();
986
+ if (exprList) {
987
+ exprList.expr().map(item => {
988
+ const exprType = traverseExpr(item, constraints, parameters, dbSchema, withSchema, fromColumns);
989
+ return exprType;
990
+ });
991
+ /*
992
+ The result type is TEXT or BLOB unless group_concat_max_len is less than or equal to 512,
993
+ in which case the result type is VARCHAR or VARBINARY.
994
+ */
995
+ //TODO - Infer TEXT/BLOB or VARCHAR/VARBINARY
996
+ return (0, collect_constraints_1.freshVar)(sumExpr.text, 'varchar');
997
+ ;
998
+ }
999
+ }
1000
+ throw Error('Expression not supported: ' + sumExpr.constructor.name);
1001
+ }
1002
+ if (simpleExpr instanceof ts_mysql_parser_1.SimpleExprRuntimeFunctionContext) {
1003
+ const runtimeFunctionCall = simpleExpr.runtimeFunctionCall();
1004
+ if (runtimeFunctionCall.NOW_SYMBOL()) {
1005
+ return (0, collect_constraints_1.freshVar)(simpleExpr.text, 'datetime');
1006
+ }
1007
+ if (runtimeFunctionCall.CURDATE_SYMBOL()) {
1008
+ return (0, collect_constraints_1.freshVar)(simpleExpr.text, 'date');
1009
+ }
1010
+ if (runtimeFunctionCall.CURTIME_SYMBOL()) {
1011
+ return (0, collect_constraints_1.freshVar)(simpleExpr.text, 'time');
1012
+ }
1013
+ if (runtimeFunctionCall.REPLACE_SYMBOL()) {
1014
+ const exprList = runtimeFunctionCall.expr();
1015
+ exprList.forEach(expr => {
1016
+ const exprType = traverseExpr(expr, constraints, parameters, dbSchema, withSchema, fromColumns);
1017
+ constraints.push({
1018
+ expression: expr.text,
1019
+ type1: exprType,
1020
+ type2: (0, collect_constraints_1.freshVar)('varchar', 'varchar')
1021
+ });
1022
+ });
1023
+ return (0, collect_constraints_1.freshVar)('varchar', 'varchar');
1024
+ }
1025
+ if (runtimeFunctionCall.YEAR_SYMBOL() || runtimeFunctionCall.MONTH_SYMBOL() || runtimeFunctionCall.DAY_SYMBOL()) {
1026
+ const expr = (_g = runtimeFunctionCall.exprWithParentheses()) === null || _g === void 0 ? void 0 : _g.expr();
1027
+ if (expr) {
1028
+ const paramType = traverseExpr(expr, constraints, parameters, dbSchema, withSchema, fromColumns);
1029
+ if (paramType.kind == 'TypeVar' && (0, collect_constraints_1.isDateTimeLiteral)(paramType.name)) {
1030
+ paramType.type = 'datetime';
1031
+ }
1032
+ if (paramType.kind == 'TypeVar' && (0, collect_constraints_1.isDateLiteral)(paramType.name)) {
1033
+ paramType.type = 'date';
1034
+ }
1035
+ constraints.push({
1036
+ expression: expr.text,
1037
+ type1: paramType,
1038
+ type2: (0, collect_constraints_1.freshVar)(simpleExpr.text, 'date')
1039
+ });
1040
+ }
1041
+ const returnType = runtimeFunctionCall.YEAR_SYMBOL() ? 'year' : 'tinyint';
1042
+ return (0, collect_constraints_1.freshVar)(simpleExpr.text, returnType);
1043
+ }
1044
+ if (runtimeFunctionCall.HOUR_SYMBOL() || runtimeFunctionCall.MINUTE_SYMBOL() || runtimeFunctionCall.SECOND_SYMBOL()) {
1045
+ const expr = (_h = runtimeFunctionCall.exprWithParentheses()) === null || _h === void 0 ? void 0 : _h.expr();
1046
+ if (expr) {
1047
+ const paramType = traverseExpr(expr, constraints, parameters, dbSchema, withSchema, fromColumns);
1048
+ if (paramType.kind == 'TypeVar' && (0, collect_constraints_1.isTimeLiteral)(paramType.name)) {
1049
+ paramType.type = 'time';
1050
+ }
1051
+ if (paramType.kind == 'TypeVar' && (0, collect_constraints_1.isDateLiteral)(paramType.name)) {
1052
+ paramType.type = 'date';
1053
+ }
1054
+ if (paramType.kind == 'TypeVar' && (0, collect_constraints_1.isDateTimeLiteral)(paramType.name)) {
1055
+ paramType.type = 'datetime';
1056
+ }
1057
+ constraints.push({
1058
+ expression: expr.text,
1059
+ type1: paramType,
1060
+ type2: (0, collect_constraints_1.freshVar)(simpleExpr.text, 'time')
1061
+ });
1062
+ }
1063
+ //HOUR can return values greater than 23. Ex.: SELECT HOUR('272:59:59');
1064
+ //https://dev.mysql.com/doc/refman/8.0/en/date-and-time-functions.html#function_hour
1065
+ const returnType = runtimeFunctionCall.HOUR_SYMBOL() ? 'int' : 'tinyint';
1066
+ return (0, collect_constraints_1.freshVar)(simpleExpr.text, returnType);
1067
+ }
1068
+ const trimFunction = runtimeFunctionCall.trimFunction();
1069
+ if (trimFunction) {
1070
+ const exprList = trimFunction.expr();
1071
+ if (exprList.length == 1) {
1072
+ const exprType = traverseExpr(exprList[0], constraints, parameters, dbSchema, withSchema, fromColumns);
1073
+ constraints.push({
1074
+ expression: exprList[0].text,
1075
+ type1: exprType,
1076
+ type2: (0, collect_constraints_1.freshVar)('varchar', 'varchar')
1077
+ });
1078
+ }
1079
+ if (exprList.length == 2) {
1080
+ const exprType = traverseExpr(exprList[0], constraints, parameters, dbSchema, withSchema, fromColumns);
1081
+ const expr2Type = traverseExpr(exprList[1], constraints, parameters, dbSchema, withSchema, fromColumns);
1082
+ constraints.push({
1083
+ expression: exprList[0].text,
1084
+ type1: exprType,
1085
+ type2: (0, collect_constraints_1.freshVar)('varchar', 'varchar')
1086
+ });
1087
+ constraints.push({
1088
+ expression: exprList[1].text,
1089
+ type1: expr2Type,
1090
+ type2: (0, collect_constraints_1.freshVar)('varchar', 'varchar')
1091
+ });
1092
+ }
1093
+ return (0, collect_constraints_1.freshVar)('varchar', 'varchar');
1094
+ }
1095
+ const substringFunction = runtimeFunctionCall.substringFunction();
1096
+ if (substringFunction) {
1097
+ const exprList = substringFunction.expr();
1098
+ const varcharParam = (0, collect_constraints_1.freshVar)('varchar', 'varchar');
1099
+ const intParam = (0, collect_constraints_1.freshVar)('int', 'int');
1100
+ const params = {
1101
+ kind: 'FixedLengthParams',
1102
+ paramsType: [varcharParam, intParam, intParam]
1103
+ };
1104
+ traverseExprListParameters(exprList, params, constraints, parameters, dbSchema, withSchema, fromColumns);
1105
+ return varcharParam;
1106
+ }
1107
+ if (runtimeFunctionCall.ADDDATE_SYMBOL()
1108
+ || runtimeFunctionCall.DATE_ADD_SYMBOL()
1109
+ || runtimeFunctionCall.SUBDATE_SYMBOL()
1110
+ || runtimeFunctionCall.DATE_SUB_SYMBOL()) {
1111
+ //SELECT ADDDATE('2008-01-02', INTERVAL 31 DAY)
1112
+ //SELECT ADDDATE('2008-01-02', 31)
1113
+ const expr1 = runtimeFunctionCall.expr()[0];
1114
+ const expr2 = runtimeFunctionCall.expr()[1];
1115
+ const typeExpr1 = traverseExpr(expr1, constraints, parameters, dbSchema, withSchema, fromColumns);
1116
+ const typeExpr2 = traverseExpr(expr2, constraints, parameters, dbSchema, withSchema, fromColumns);
1117
+ if (typeExpr1.kind == 'TypeVar' && ((0, collect_constraints_1.isDateLiteral)(typeExpr1.name) || (0, collect_constraints_1.isDateTimeLiteral)(typeExpr1.name))) {
1118
+ typeExpr1.type = 'datetime';
1119
+ }
1120
+ constraints.push({
1121
+ expression: expr1.text,
1122
+ type1: typeExpr1,
1123
+ type2: (0, collect_constraints_1.freshVar)('datetime', 'datetime')
1124
+ });
1125
+ constraints.push({
1126
+ expression: expr2.text,
1127
+ type1: typeExpr2,
1128
+ type2: (0, collect_constraints_1.freshVar)('bigint', 'bigint')
1129
+ });
1130
+ return (0, collect_constraints_1.freshVar)('datetime', 'datetime');
1131
+ }
1132
+ if (runtimeFunctionCall.COALESCE_SYMBOL()) {
1133
+ const exprList = (_j = runtimeFunctionCall.exprListWithParentheses()) === null || _j === void 0 ? void 0 : _j.exprList().expr();
1134
+ if (exprList) {
1135
+ const paramType = (0, collect_constraints_1.freshVar)('COALESCE', 'any');
1136
+ const params = {
1137
+ kind: 'VariableLengthParams',
1138
+ paramType: '?'
1139
+ };
1140
+ const paramsTypeList = traverseExprListParameters(exprList, params, constraints, parameters, dbSchema, withSchema, fromColumns);
1141
+ paramsTypeList.forEach((typeVar, paramIndex) => {
1142
+ constraints.push({
1143
+ expression: runtimeFunctionCall.text + '_param' + (paramIndex + 1),
1144
+ type1: paramType,
1145
+ type2: typeVar,
1146
+ mostGeneralType: true,
1147
+ coercionType: 'Coalesce'
1148
+ });
1149
+ });
1150
+ return paramType;
1151
+ }
1152
+ }
1153
+ //MOD (number, number): number
1154
+ if (runtimeFunctionCall.MOD_SYMBOL()) {
1155
+ const functionType = (0, collect_constraints_1.freshVar)('number', 'number');
1156
+ const exprList = runtimeFunctionCall.expr();
1157
+ const param1 = traverseExpr(exprList[0], constraints, parameters, dbSchema, withSchema, fromColumns);
1158
+ const param2 = traverseExpr(exprList[1], constraints, parameters, dbSchema, withSchema, fromColumns);
1159
+ constraints.push({
1160
+ expression: simpleExpr.text,
1161
+ type1: (0, collect_constraints_1.freshVar)('number', 'number'),
1162
+ type2: param1,
1163
+ mostGeneralType: true,
1164
+ coercionType: 'Numeric'
1165
+ });
1166
+ constraints.push({
1167
+ expression: simpleExpr.text,
1168
+ type1: (0, collect_constraints_1.freshVar)('number', 'number'),
1169
+ type2: param2,
1170
+ mostGeneralType: true,
1171
+ coercionType: 'Numeric'
1172
+ });
1173
+ constraints.push({
1174
+ expression: simpleExpr.text,
1175
+ type1: functionType,
1176
+ type2: param1,
1177
+ mostGeneralType: true
1178
+ });
1179
+ constraints.push({
1180
+ expression: simpleExpr.text,
1181
+ type1: functionType,
1182
+ type2: param2,
1183
+ mostGeneralType: true
1184
+ });
1185
+ return functionType;
1186
+ }
1187
+ if (runtimeFunctionCall.IF_SYMBOL()) {
1188
+ const exprList = runtimeFunctionCall.expr();
1189
+ const expr1 = exprList[0];
1190
+ const expr2 = exprList[1];
1191
+ const expr3 = exprList[2];
1192
+ traverseExpr(expr1, constraints, parameters, dbSchema, withSchema, fromColumns);
1193
+ const expr2Type = traverseExpr(expr2, constraints, parameters, dbSchema, withSchema, fromColumns);
1194
+ const expr3Type = traverseExpr(expr3, constraints, parameters, dbSchema, withSchema, fromColumns);
1195
+ constraints.push({
1196
+ expression: runtimeFunctionCall.text,
1197
+ type1: expr2Type,
1198
+ type2: expr3Type,
1199
+ mostGeneralType: true
1200
+ });
1201
+ return expr2Type;
1202
+ }
1203
+ throw Error('Function not supported: ' + runtimeFunctionCall.text);
1204
+ }
1205
+ if (simpleExpr instanceof ts_mysql_parser_1.SimpleExprFunctionContext) {
1206
+ const functionIdentifier = (0, collect_constraints_1.getFunctionName)(simpleExpr);
1207
+ if (functionIdentifier === 'concat_ws' || (functionIdentifier === null || functionIdentifier === void 0 ? void 0 : functionIdentifier.toLowerCase()) === 'concat') {
1208
+ const varcharType = (0, collect_constraints_1.freshVar)(simpleExpr.text, 'varchar');
1209
+ const params = {
1210
+ kind: 'VariableLengthParams',
1211
+ paramType: 'varchar'
1212
+ };
1213
+ walkFunctionParameters(simpleExpr, params, constraints, parameters, dbSchema, withSchema, fromColumns);
1214
+ return varcharType;
1215
+ }
1216
+ if (functionIdentifier === 'avg') {
1217
+ const functionType = (0, collect_constraints_1.freshVar)(simpleExpr.text, '?');
1218
+ constraints.push({
1219
+ expression: simpleExpr.text,
1220
+ type1: functionType,
1221
+ type2: (0, collect_constraints_1.freshVar)('decimal', 'decimal'),
1222
+ mostGeneralType: true
1223
+ });
1224
+ const params = {
1225
+ kind: 'FixedLengthParams',
1226
+ paramsType: [functionType]
1227
+ };
1228
+ walkFunctionParameters(simpleExpr, params, constraints, parameters, dbSchema, withSchema, fromColumns);
1229
+ return functionType;
1230
+ }
1231
+ if (functionIdentifier === 'round') {
1232
+ const functionType = (0, collect_constraints_1.freshVar)(simpleExpr.text, '?');
1233
+ const params = {
1234
+ kind: 'FixedLengthParams',
1235
+ paramsType: [functionType]
1236
+ };
1237
+ const paramsType = walkFunctionParameters(simpleExpr, params, constraints, parameters, dbSchema, withSchema, fromColumns);
1238
+ //The return value has the same type as the first argument
1239
+ constraints.push({
1240
+ expression: simpleExpr.text,
1241
+ type1: functionType,
1242
+ type2: paramsType[0],
1243
+ mostGeneralType: true
1244
+ });
1245
+ return functionType;
1246
+ }
1247
+ if (functionIdentifier === 'floor') {
1248
+ const doubleParam = (0, collect_constraints_1.freshVar)('double', 'double');
1249
+ const params = {
1250
+ kind: 'FixedLengthParams',
1251
+ paramsType: [doubleParam, doubleParam]
1252
+ };
1253
+ walkFunctionParameters(simpleExpr, params, constraints, parameters, dbSchema, withSchema, fromColumns);
1254
+ return (0, collect_constraints_1.freshVar)(simpleExpr.text, 'bigint');
1255
+ }
1256
+ if (functionIdentifier === 'str_to_date') {
1257
+ const varcharParam = (0, collect_constraints_1.freshVar)('varchar', 'varchar');
1258
+ const params = {
1259
+ kind: 'FixedLengthParams',
1260
+ paramsType: [varcharParam, varcharParam]
1261
+ };
1262
+ walkFunctionParameters(simpleExpr, params, constraints, parameters, dbSchema, withSchema, fromColumns);
1263
+ return (0, collect_constraints_1.freshVar)(simpleExpr.text, 'date');
1264
+ }
1265
+ if (functionIdentifier === 'datediff') {
1266
+ const udfExprList = (_k = simpleExpr.functionCall().udfExprList()) === null || _k === void 0 ? void 0 : _k.udfExpr();
1267
+ if (udfExprList) {
1268
+ udfExprList.forEach((inExpr) => {
1269
+ const expr = inExpr.expr();
1270
+ const exprType = traverseExpr(expr, constraints, parameters, dbSchema, withSchema, fromColumns);
1271
+ const newType = (0, collect_constraints_1.verifyDateTypesCoercion)(exprType);
1272
+ constraints.push({
1273
+ expression: expr.text,
1274
+ type1: newType,
1275
+ type2: (0, collect_constraints_1.freshVar)('date', 'date'),
1276
+ mostGeneralType: true
1277
+ });
1278
+ });
1279
+ }
1280
+ return (0, collect_constraints_1.freshVar)(simpleExpr.text, 'bigint');
1281
+ }
1282
+ if (functionIdentifier === 'lpad' || functionIdentifier == 'rpad') {
1283
+ const varcharParam = (0, collect_constraints_1.freshVar)('varchar', 'varchar');
1284
+ const intParam = (0, collect_constraints_1.freshVar)('int', 'int');
1285
+ const params = {
1286
+ kind: 'FixedLengthParams',
1287
+ paramsType: [varcharParam, intParam, varcharParam]
1288
+ };
1289
+ walkFunctionParameters(simpleExpr, params, constraints, parameters, dbSchema, withSchema, fromColumns);
1290
+ return varcharParam;
1291
+ }
1292
+ if (functionIdentifier === 'lower'
1293
+ || functionIdentifier === 'lcase'
1294
+ || functionIdentifier === 'upper'
1295
+ || functionIdentifier === 'ucase'
1296
+ || functionIdentifier === 'trim'
1297
+ || functionIdentifier === 'ltrim'
1298
+ || functionIdentifier === 'rtrim') {
1299
+ const varcharParam = (0, collect_constraints_1.freshVar)('varchar', 'varchar');
1300
+ const params = {
1301
+ kind: 'FixedLengthParams',
1302
+ paramsType: [varcharParam]
1303
+ };
1304
+ walkFunctionParameters(simpleExpr, params, constraints, parameters, dbSchema, withSchema, fromColumns);
1305
+ return varcharParam;
1306
+ }
1307
+ if (functionIdentifier === 'length' || functionIdentifier == 'char_length') {
1308
+ const varcharParam = (0, collect_constraints_1.freshVar)('varchar', 'varchar');
1309
+ const params = {
1310
+ kind: 'FixedLengthParams',
1311
+ paramsType: [varcharParam]
1312
+ };
1313
+ walkFunctionParameters(simpleExpr, params, constraints, parameters, dbSchema, withSchema, fromColumns);
1314
+ return (0, collect_constraints_1.freshVar)('int', 'int');
1315
+ }
1316
+ if (functionIdentifier === 'abs') {
1317
+ const functionType = (0, collect_constraints_1.freshVar)('number', 'number');
1318
+ const udfExprList = (_l = simpleExpr.functionCall().udfExprList()) === null || _l === void 0 ? void 0 : _l.udfExpr();
1319
+ udfExprList === null || udfExprList === void 0 ? void 0 : udfExprList.forEach(expr => {
1320
+ const param1 = traverseExpr(expr.expr(), constraints, parameters, dbSchema, withSchema, fromColumns);
1321
+ constraints.push({
1322
+ expression: simpleExpr.text,
1323
+ type1: functionType,
1324
+ type2: param1,
1325
+ mostGeneralType: true,
1326
+ coercionType: 'Numeric'
1327
+ });
1328
+ });
1329
+ return functionType;
1330
+ }
1331
+ if (functionIdentifier == 'ceiling' || functionIdentifier == 'ceil') {
1332
+ const functionType = (0, collect_constraints_1.freshVar)('number', 'number');
1333
+ const udfExprList = (_m = simpleExpr.functionCall().udfExprList()) === null || _m === void 0 ? void 0 : _m.udfExpr();
1334
+ udfExprList === null || udfExprList === void 0 ? void 0 : udfExprList.forEach(expr => {
1335
+ const param1 = traverseExpr(expr.expr(), constraints, parameters, dbSchema, withSchema, fromColumns);
1336
+ constraints.push({
1337
+ expression: simpleExpr.text,
1338
+ type1: functionType,
1339
+ type2: param1,
1340
+ mostGeneralType: true,
1341
+ coercionType: 'Ceiling'
1342
+ });
1343
+ });
1344
+ return functionType;
1345
+ }
1346
+ if (functionIdentifier == 'timestampdiff') {
1347
+ const udfExprList = (_o = simpleExpr.functionCall().udfExprList()) === null || _o === void 0 ? void 0 : _o.udfExpr();
1348
+ if (udfExprList) {
1349
+ const [first, ...rest] = udfExprList;
1350
+ const unit = first.text.trim().toLowerCase();
1351
+ rest.forEach((inExpr, paramIndex) => {
1352
+ const expr = inExpr.expr();
1353
+ const exprType = traverseExpr(expr, constraints, parameters, dbSchema, withSchema, fromColumns);
1354
+ const newType = (0, collect_constraints_1.verifyDateTypesCoercion)(exprType);
1355
+ //const expectedType = ['hour', 'minute', 'second'].includes(unit)? 'time' : 'datetime'
1356
+ constraints.push({
1357
+ expression: expr.text,
1358
+ type1: newType,
1359
+ type2: (0, collect_constraints_1.freshVar)('datetime', 'datetime'),
1360
+ mostGeneralType: true
1361
+ });
1362
+ });
1363
+ }
1364
+ return (0, collect_constraints_1.freshVar)('int', 'int');
1365
+ }
1366
+ if (functionIdentifier == 'ifnull' || functionIdentifier == 'nullif') {
1367
+ const functionType = (0, collect_constraints_1.freshVar)(simpleExpr.text, '?');
1368
+ const udfExprList = (_p = simpleExpr.functionCall().udfExprList()) === null || _p === void 0 ? void 0 : _p.udfExpr();
1369
+ if (udfExprList) {
1370
+ const [expr1, expr2] = udfExprList;
1371
+ const expr1Type = traverseExpr(expr1.expr(), constraints, parameters, dbSchema, withSchema, fromColumns);
1372
+ constraints.push({
1373
+ expression: expr1.text,
1374
+ type1: functionType,
1375
+ type2: expr1Type
1376
+ });
1377
+ const expr2Type = traverseExpr(expr2.expr(), constraints, parameters, dbSchema, withSchema, fromColumns);
1378
+ constraints.push({
1379
+ expression: expr2.text,
1380
+ type1: functionType,
1381
+ type2: expr2Type
1382
+ });
1383
+ }
1384
+ return functionType;
1385
+ }
1386
+ if (functionIdentifier == 'md5' //md5(str) - TODO - have input constraint = string
1387
+ || functionIdentifier == 'hex' //md5(n or str)
1388
+ || functionIdentifier == 'unhex') { //unhex (str) - TODO - have input constraint = string
1389
+ const functionType = (0, collect_constraints_1.freshVar)(simpleExpr.text, 'char');
1390
+ const udfExprList = (_q = simpleExpr.functionCall().udfExprList()) === null || _q === void 0 ? void 0 : _q.udfExpr();
1391
+ if (udfExprList) {
1392
+ const [expr1] = udfExprList;
1393
+ const paramType = traverseExpr(expr1.expr(), constraints, parameters, dbSchema, withSchema, fromColumns);
1394
+ constraints.push({
1395
+ expression: expr1.text,
1396
+ type1: paramType,
1397
+ type2: (0, collect_constraints_1.freshVar)(expr1.text, 'varchar')
1398
+ });
1399
+ }
1400
+ return functionType;
1401
+ }
1402
+ throw Error('Function not supported: ' + functionIdentifier);
1403
+ }
1404
+ if (simpleExpr instanceof ts_mysql_parser_1.SimpleExprWindowingFunctionContext) {
1405
+ const windowFunctionCall = simpleExpr.windowFunctionCall();
1406
+ return traverseWindowFunctionCall(windowFunctionCall, constraints, parameters, dbSchema, withSchema, fromColumns);
1407
+ }
1408
+ if (simpleExpr instanceof ts_mysql_parser_1.SimpleExprCastContext) {
1409
+ const castType = simpleExpr.castType();
1410
+ if (castType.CHAR_SYMBOL()) {
1411
+ return (0, collect_constraints_1.freshVar)(castType.text, 'char');
1412
+ }
1413
+ }
1414
+ throw Error('traverseSimpleExpr - not supported: ' + simpleExpr.constructor.name);
1415
+ }
1416
+ function traverseWindowFunctionCall(windowFunctionCall, constraints, parameters, dbSchema, withSchema, fromColumns) {
1417
+ if (windowFunctionCall.ROW_NUMBER_SYMBOL()
1418
+ || windowFunctionCall.RANK_SYMBOL()
1419
+ || windowFunctionCall.DENSE_RANK_SYMBOL()
1420
+ || windowFunctionCall.CUME_DIST_SYMBOL()
1421
+ || windowFunctionCall.PERCENT_RANK_SYMBOL()) {
1422
+ return (0, collect_constraints_1.freshVar)(windowFunctionCall.text, 'bigint');
1423
+ }
1424
+ const expr = windowFunctionCall.expr();
1425
+ if (expr) {
1426
+ return traverseExpr(expr, constraints, parameters, dbSchema, withSchema, fromColumns);
1427
+ }
1428
+ const exprWithParentheses = windowFunctionCall.exprWithParentheses();
1429
+ if (exprWithParentheses) {
1430
+ const expr = exprWithParentheses.expr();
1431
+ return traverseExpr(expr, constraints, parameters, dbSchema, withSchema, fromColumns);
1432
+ }
1433
+ throw Error('No support for expression' + windowFunctionCall.constructor.name);
1434
+ }
1435
+ function traverseExprListParameters(exprList, params, constraints, parameters, dbSchema, withSchema, fromColumns) {
1436
+ return exprList.map((expr, paramIndex) => {
1437
+ const exprType = traverseExpr(expr, constraints, parameters, dbSchema, withSchema, fromColumns);
1438
+ const paramType = params.kind == 'FixedLengthParams' ? params.paramsType[paramIndex] : (0, collect_constraints_1.freshVar)(params.paramType, params.paramType);
1439
+ constraints.push({
1440
+ expression: expr.text,
1441
+ type1: exprType,
1442
+ type2: paramType,
1443
+ mostGeneralType: true
1444
+ });
1445
+ return paramType;
1446
+ });
1447
+ }
1448
+ function walkFunctionParameters(simpleExprFunction, params, constraints, parameters, dbSchema, withSchema, fromColumns) {
1449
+ var _a, _b;
1450
+ const functionName = (0, collect_constraints_1.getFunctionName)(simpleExprFunction);
1451
+ const udfExprList = (_a = simpleExprFunction.functionCall().udfExprList()) === null || _a === void 0 ? void 0 : _a.udfExpr();
1452
+ if (udfExprList) {
1453
+ const paramTypes = udfExprList
1454
+ .filter((undefined, paramIndex) => {
1455
+ return functionName == 'timestampdiff' ? paramIndex != 0 : true; //filter the first parameter of timestampdiff function
1456
+ })
1457
+ .map((inExpr, paramIndex) => {
1458
+ const expr = inExpr.expr();
1459
+ const exprType = traverseExpr(expr, constraints, parameters, dbSchema, withSchema, fromColumns);
1460
+ constraints.push({
1461
+ expression: expr.text,
1462
+ type1: exprType,
1463
+ type2: params.kind == 'FixedLengthParams' ? params.paramsType[paramIndex] : (0, collect_constraints_1.freshVar)(params.paramType, params.paramType),
1464
+ });
1465
+ return exprType;
1466
+ });
1467
+ return paramTypes;
1468
+ }
1469
+ const exprList = (_b = simpleExprFunction.functionCall().exprList()) === null || _b === void 0 ? void 0 : _b.expr();
1470
+ if (exprList) {
1471
+ const paramTypes = exprList.map((inExpr, paramIndex) => {
1472
+ const inSumExprType = traverseExpr(inExpr, constraints, parameters, dbSchema, withSchema, fromColumns);
1473
+ constraints.push({
1474
+ expression: inExpr.text,
1475
+ type1: params.kind == 'FixedLengthParams' ? params.paramsType[paramIndex] : (0, collect_constraints_1.freshVar)(params.paramType, params.paramType),
1476
+ type2: inSumExprType,
1477
+ mostGeneralType: true
1478
+ });
1479
+ return inSumExprType;
1480
+ });
1481
+ return paramTypes;
1482
+ }
1483
+ throw Error('Error in walkFunctionParameters');
1484
+ }
1485
+ function filterColumns(dbSchema, withSchema, tableAlias, table) {
1486
+ const withResult = withSchema.filter(t => t.table.toLowerCase() == table.name.toLowerCase()).map(s => (Object.assign(Object.assign({}, s), { tableAlias: tableAlias })));
1487
+ const tableColumns1 = dbSchema
1488
+ .filter(schema => schema.table.toLowerCase() == table.name.toLowerCase() && (schema.schema == table.prefix || table.prefix == ''))
1489
+ .map(tableColumn => {
1490
+ //name and colum are the same on the leaf table
1491
+ const r = {
1492
+ columnName: tableColumn.column, columnType: { kind: 'TypeVar', type: tableColumn.column_type, id: tableColumn.column_type, name: tableColumn.column },
1493
+ notNull: tableColumn.notNull, table: table.name, tableAlias: tableAlias || '', columnKey: tableColumn.columnKey
1494
+ };
1495
+ return r;
1496
+ });
1497
+ const result = tableColumns1.concat(withResult);
1498
+ return result;
1499
+ }
1500
+ exports.filterColumns = filterColumns;
1501
+ function selectAllColumns(tablePrefix, fromColumns) {
1502
+ return fromColumns.filter(column => {
1503
+ if (tablePrefix == '' || tablePrefix == column.tableAlias || tablePrefix == column.table) {
1504
+ return column;
1505
+ }
1506
+ });
1507
+ }
1508
+ exports.selectAllColumns = selectAllColumns;
1509
+ function filterUsingFields(joinedFields, usingFields) {
1510
+ return joinedFields.filter(joinedField => {
1511
+ const isUsing = usingFields.includes(joinedField.columnName);
1512
+ if (!isUsing) {
1513
+ return joinedField;
1514
+ }
1515
+ });
1516
+ }
1517
+ function isMultipleRowResult(selectStatement, fromColumns) {
1518
+ var _a, _b;
1519
+ const querySpecs = (0, parse_1.getAllQuerySpecificationsFromSelectStatement)(selectStatement);
1520
+ if (querySpecs.length == 1) { //UNION queries are multipleRowsResult = true
1521
+ const fromClause = querySpecs[0].fromClause();
1522
+ if (!fromClause) {
1523
+ return false;
1524
+ }
1525
+ if (querySpecs[0].selectItemList().childCount == 1) {
1526
+ const selectItem = querySpecs[0].selectItemList().getChild(0);
1527
+ //if selectItem = * (TerminalNode) childCount = 0; selectItem.expr() throws exception
1528
+ const expr = selectItem.childCount > 0 ? selectItem.expr() : null;
1529
+ if (expr) {
1530
+ //SUM, MAX... WITHOUT GROUP BY are multipleRowsResult = false
1531
+ const groupBy = querySpecs[0].groupByClause();
1532
+ if (!groupBy && (0, parse_1.isSumExpressContext)(expr)) {
1533
+ return false;
1534
+ }
1535
+ }
1536
+ }
1537
+ const joinedTable = (_a = fromClause.tableReferenceList()) === null || _a === void 0 ? void 0 : _a.tableReference()[0].joinedTable();
1538
+ if (joinedTable && joinedTable.length > 0) {
1539
+ return true;
1540
+ }
1541
+ const whereClauseExpr = (_b = querySpecs[0].whereClause()) === null || _b === void 0 ? void 0 : _b.expr();
1542
+ const isMultipleRowResult = whereClauseExpr && verifyMultipleResult2(whereClauseExpr, fromColumns);
1543
+ if (isMultipleRowResult == false) {
1544
+ return false;
1545
+ }
1546
+ }
1547
+ const limitOptions = (0, parse_1.getLimitOptions)(selectStatement);
1548
+ if (limitOptions.length == 1 && limitOptions[0].text == '1') {
1549
+ return false;
1550
+ }
1551
+ if (limitOptions.length == 2 && limitOptions[1].text == '1') {
1552
+ return false;
1553
+ }
1554
+ return true;
1555
+ }
1556
+ exports.isMultipleRowResult = isMultipleRowResult;
1557
+ function verifyMultipleResult2(exprContext, fromColumns) {
1558
+ if (exprContext instanceof ts_mysql_parser_1.ExprIsContext) {
1559
+ const boolPri = exprContext.boolPri();
1560
+ if (boolPri instanceof ts_mysql_parser_1.PrimaryExprCompareContext) {
1561
+ if (boolPri.compOp().EQUAL_OPERATOR()) {
1562
+ let compareLeft = boolPri.boolPri();
1563
+ let compareRight = boolPri.predicate();
1564
+ if (isUniqueKeyComparation(compareLeft, fromColumns) || isUniqueKeyComparation(compareRight, fromColumns)) {
1565
+ return false; //multipleRow = false
1566
+ }
1567
+ }
1568
+ return true; //multipleRow = true
1569
+ }
1570
+ return true; //multipleRow
1571
+ }
1572
+ if (exprContext instanceof ts_mysql_parser_1.ExprNotContext) {
1573
+ return true;
1574
+ }
1575
+ if (exprContext instanceof ts_mysql_parser_1.ExprAndContext) {
1576
+ const oneIsSingleResult = exprContext.expr().some(expr => verifyMultipleResult2(expr, fromColumns) == false);
1577
+ return oneIsSingleResult == false;
1578
+ }
1579
+ // if (exprContext instanceof ExprXorContext) {
1580
+ // const expressions = exprContext.expr();
1581
+ // }
1582
+ if (exprContext instanceof ts_mysql_parser_1.ExprOrContext) {
1583
+ return true; //multipleRow = true
1584
+ }
1585
+ throw Error('Unknow type:' + exprContext.constructor.name);
1586
+ }
1587
+ exports.verifyMultipleResult2 = verifyMultipleResult2;
1588
+ function isUniqueKeyComparation(compare, fromColumns) {
1589
+ const tokens = (0, select_columns_1.getSimpleExpressions)(compare);
1590
+ if (tokens.length == 1 && tokens[0] instanceof ts_mysql_parser_1.SimpleExprColumnRefContext) {
1591
+ const fieldName = (0, select_columns_1.splitName)(tokens[0].text);
1592
+ const col = (0, select_columns_1.findColumn)(fieldName, fromColumns);
1593
+ if (col.columnKey == 'PRI' || col.columnKey == 'UNI') { //TODO - UNIQUE
1594
+ return true; //isUniqueKeyComparation = true
1595
+ }
1596
+ }
1597
+ return false; //isUniqueKeyComparation = false
1598
+ }
1599
+ function getOrderByColumns(fromColumns, selectColumns) {
1600
+ const fromColumnsNames = fromColumns.map(col => col.columnName); //TODO - loading twice
1601
+ const selectColumnsNames = selectColumns.map(col => col.name);
1602
+ const allOrderByColumns = Array.from(new Set(fromColumnsNames.concat(selectColumnsNames)));
1603
+ return allOrderByColumns;
1604
+ }
1605
+ //# sourceMappingURL=traverse.js.map