typesql-cli 0.4.7 → 0.4.9

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 (55) hide show
  1. package/cli.d.ts +2 -2
  2. package/cli.js +228 -220
  3. package/cli.js.map +1 -1
  4. package/code-generator.d.ts +19 -19
  5. package/code-generator.d.ts.map +1 -1
  6. package/code-generator.js +269 -265
  7. package/code-generator.js.map +1 -1
  8. package/describe-query.d.ts +9 -9
  9. package/describe-query.js +168 -168
  10. package/describe-query.js.map +1 -1
  11. package/mysql-mapping.d.ts +18 -18
  12. package/mysql-mapping.d.ts.map +1 -1
  13. package/mysql-mapping.js +146 -146
  14. package/mysql-mapping.js.map +1 -1
  15. package/mysql-query-analyzer/collect-constraints.d.ts +50 -50
  16. package/mysql-query-analyzer/collect-constraints.d.ts.map +1 -1
  17. package/mysql-query-analyzer/collect-constraints.js +1196 -1195
  18. package/mysql-query-analyzer/collect-constraints.js.map +1 -1
  19. package/mysql-query-analyzer/infer-column-nullability.d.ts +5 -5
  20. package/mysql-query-analyzer/infer-column-nullability.js +307 -307
  21. package/mysql-query-analyzer/infer-column-nullability.js.map +1 -1
  22. package/mysql-query-analyzer/infer-param-nullability.d.ts +6 -6
  23. package/mysql-query-analyzer/infer-param-nullability.js +78 -78
  24. package/mysql-query-analyzer/infer-param-nullability.js.map +1 -1
  25. package/mysql-query-analyzer/parse.d.ts +14 -14
  26. package/mysql-query-analyzer/parse.d.ts.map +1 -1
  27. package/mysql-query-analyzer/parse.js +219 -215
  28. package/mysql-query-analyzer/parse.js.map +1 -1
  29. package/mysql-query-analyzer/select-columns.d.ts +12 -12
  30. package/mysql-query-analyzer/select-columns.js +373 -373
  31. package/mysql-query-analyzer/select-columns.js.map +1 -1
  32. package/mysql-query-analyzer/types.d.ts +72 -72
  33. package/mysql-query-analyzer/types.d.ts.map +1 -1
  34. package/mysql-query-analyzer/types.js +2 -2
  35. package/mysql-query-analyzer/unify.d.ts +4 -4
  36. package/mysql-query-analyzer/unify.js +157 -157
  37. package/mysql-query-analyzer/util.d.ts +6 -6
  38. package/mysql-query-analyzer/util.d.ts.map +1 -1
  39. package/mysql-query-analyzer/util.js +30 -30
  40. package/mysql-query-analyzer/verify-multiple-result.d.ts +3 -3
  41. package/mysql-query-analyzer/verify-multiple-result.js +47 -47
  42. package/mysql-query-analyzer/verify-multiple-result.js.map +1 -1
  43. package/package.json +4 -5
  44. package/queryExectutor.d.ts +15 -13
  45. package/queryExectutor.d.ts.map +1 -1
  46. package/queryExectutor.js +107 -104
  47. package/queryExectutor.js.map +1 -1
  48. package/sql-generator.d.ts +5 -5
  49. package/sql-generator.js +88 -88
  50. package/types.d.ts +89 -89
  51. package/types.d.ts.map +1 -1
  52. package/types.js +2 -2
  53. package/utility-types.d.ts +4 -4
  54. package/utility-types.d.ts.map +1 -1
  55. package/utility-types.js +2 -2
@@ -1,1196 +1,1197 @@
1
- "use strict";
2
- var __importDefault = (this && this.__importDefault) || function (mod) {
3
- return (mod && mod.__esModule) ? mod : { "default": mod };
4
- };
5
- Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.walkSubquery = exports.walkQuerySpecification = exports.generateTypeInfo = exports.analiseQuerySpecification = exports.unionTypeResult = exports.analiseSelectStatement = exports.getDeleteColumns = exports.getUpdateColumns = exports.getInsertColumns = exports.analiseUpdateStatement = exports.analiseDeleteStatement = exports.analiseInsertStatement = exports.analiseTree = exports.freshVar = void 0;
7
- const moment_1 = __importDefault(require("moment"));
8
- const ts_mysql_parser_1 = require("ts-mysql-parser");
9
- const select_columns_1 = require("./select-columns");
10
- const parse_1 = require("./parse");
11
- const unify_1 = require("./unify");
12
- const infer_param_nullability_1 = require("./infer-param-nullability");
13
- const describe_query_1 = require("../describe-query");
14
- const util_1 = require("./util");
15
- let counter = 0;
16
- function freshVar(name, typeVar, selectItem, list) {
17
- const param = {
18
- kind: 'TypeVar',
19
- id: ++counter,
20
- name,
21
- type: typeVar
22
- };
23
- if (list) {
24
- param.list = true;
25
- }
26
- if (selectItem) {
27
- param.selectItem = true;
28
- }
29
- return param;
30
- }
31
- exports.freshVar = freshVar;
32
- function analiseTree(tree, dbSchema, namedParameters) {
33
- var _a, _b, _c;
34
- if (tree instanceof ts_mysql_parser_1.QueryContext) {
35
- const selectStatement = (_a = tree.simpleStatement()) === null || _a === void 0 ? void 0 : _a.selectStatement();
36
- if (selectStatement) {
37
- return analiseSelectStatement(selectStatement, dbSchema, namedParameters);
38
- }
39
- const insertStatement = (_b = tree.simpleStatement()) === null || _b === void 0 ? void 0 : _b.insertStatement();
40
- if (insertStatement) {
41
- const insertStmt = analiseInsertStatement(insertStatement, dbSchema);
42
- const TypeInfer = {
43
- columns: [],
44
- parameters: insertStmt.parameters.map(param => param.columnType)
45
- };
46
- return TypeInfer;
47
- }
48
- const updateStatement = (_c = tree.simpleStatement()) === null || _c === void 0 ? void 0 : _c.updateStatement();
49
- if (updateStatement) {
50
- const updateStmt = analiseUpdateStatement(updateStatement, dbSchema);
51
- const TypeInfer = {
52
- columns: [],
53
- parameters: updateStmt.data.map(param => param.columnType)
54
- };
55
- return TypeInfer;
56
- }
57
- }
58
- throw Error('invalid type of tree');
59
- }
60
- exports.analiseTree = analiseTree;
61
- function analiseInsertStatement(insertStatement, dbSchema) {
62
- const valuesContext = insertStatement.insertFromConstructor().insertValues().valueList().values()[0];
63
- const insertColumns = getInsertColumns(insertStatement, dbSchema);
64
- const allParameters = [];
65
- const exprOrDefaultList = [];
66
- valuesContext.DEFAULT_SYMBOL().forEach(terminalNode => {
67
- exprOrDefaultList.push(terminalNode);
68
- });
69
- valuesContext.expr().forEach(expr => {
70
- exprOrDefaultList.push(expr);
71
- });
72
- //order the tokens based on sql position
73
- exprOrDefaultList.sort((token1, token2) => token1.sourceInterval.a - token2.sourceInterval.a);
74
- exprOrDefaultList.forEach((expr, index) => {
75
- const context = {
76
- dbSchema,
77
- constraints: [],
78
- parameters: [],
79
- fromColumns: []
80
- };
81
- const column = insertColumns[index];
82
- if (expr instanceof ts_mysql_parser_1.ExprContext) {
83
- const exprType = walkExpr(context, expr);
84
- context.constraints.push({
85
- expression: expr.text,
86
- type1: freshVar(column.column, column.column_type),
87
- type2: exprType.kind == 'TypeOperator' ? exprType.types[0] : exprType
88
- });
89
- }
90
- const typeInfo = generateTypeInfo(context.parameters, context.constraints);
91
- typeInfo.forEach(param => {
92
- allParameters.push({
93
- name: 'param' + (allParameters.length + 1),
94
- columnType: describe_query_1.verifyNotInferred(param),
95
- notNull: column.notNull
96
- });
97
- });
98
- });
99
- const typeInferenceResult = {
100
- kind: 'Insert',
101
- parameters: allParameters
102
- };
103
- return typeInferenceResult;
104
- }
105
- exports.analiseInsertStatement = analiseInsertStatement;
106
- function analiseDeleteStatement(deleteStatement, dbSchema) {
107
- var _a;
108
- const whereExpr = (_a = deleteStatement.whereClause()) === null || _a === void 0 ? void 0 : _a.expr();
109
- const deleteColumns = getDeleteColumns(deleteStatement, dbSchema);
110
- const allParameters = [];
111
- if (whereExpr) {
112
- const context = {
113
- fromColumns: deleteColumns,
114
- parameters: [],
115
- constraints: [],
116
- dbSchema
117
- };
118
- walkExpr(context, whereExpr);
119
- const typeInfo = generateTypeInfo(context.parameters, context.constraints);
120
- const paramNullability = infer_param_nullability_1.inferParamNullability(whereExpr);
121
- typeInfo.forEach((param, paramIndex) => {
122
- allParameters.push({
123
- name: 'param' + (allParameters.length + 1),
124
- columnType: describe_query_1.verifyNotInferred(param),
125
- notNull: paramNullability[paramIndex]
126
- });
127
- });
128
- }
129
- const typeInferenceResult = {
130
- kind: 'Delete',
131
- parameters: allParameters
132
- };
133
- return typeInferenceResult;
134
- }
135
- exports.analiseDeleteStatement = analiseDeleteStatement;
136
- function analiseUpdateStatement(updateStatement, dbSchema) {
137
- var _a;
138
- const updateElement = updateStatement.updateList().updateElement();
139
- const updateColumns = getUpdateColumns(updateStatement, dbSchema);
140
- const dataParameters = [];
141
- const whereParameters = [];
142
- updateElement.forEach(updateElement => {
143
- const expr = updateElement.expr();
144
- if (expr) {
145
- const context = {
146
- dbSchema,
147
- parameters: [],
148
- constraints: [],
149
- fromColumns: updateColumns
150
- };
151
- const result = walkExpr(context, expr);
152
- const columnName = updateElement.columnRef().text;
153
- const field = select_columns_1.splitName(columnName);
154
- const column = select_columns_1.findColumn(field, updateColumns);
155
- context.constraints.push({
156
- expression: updateStatement.text,
157
- type1: result,
158
- type2: freshVar(column.table, column.columnType)
159
- });
160
- const typeInfo = generateTypeInfo(context.parameters, context.constraints);
161
- typeInfo.forEach(param => {
162
- dataParameters.push({
163
- name: column.columnName,
164
- columnType: describe_query_1.verifyNotInferred(param),
165
- notNull: column.notNull
166
- });
167
- });
168
- }
169
- });
170
- const whereExpr = (_a = updateStatement.whereClause()) === null || _a === void 0 ? void 0 : _a.expr();
171
- if (whereExpr) {
172
- const context = {
173
- dbSchema,
174
- parameters: [],
175
- constraints: [],
176
- fromColumns: updateColumns
177
- };
178
- walkExpr(context, whereExpr);
179
- const typeInfo = generateTypeInfo(context.parameters, context.constraints);
180
- const paramNullability = infer_param_nullability_1.inferParamNullability(whereExpr);
181
- typeInfo.forEach((param, paramIndex) => {
182
- whereParameters.push({
183
- name: 'param' + (whereParameters.length + 1),
184
- columnType: describe_query_1.verifyNotInferred(param),
185
- notNull: paramNullability[paramIndex]
186
- });
187
- });
188
- }
189
- const typeInferenceResult = {
190
- kind: 'Update',
191
- data: dataParameters,
192
- parameters: whereParameters
193
- };
194
- return typeInferenceResult;
195
- }
196
- exports.analiseUpdateStatement = analiseUpdateStatement;
197
- function getInsertColumns(insertStatement, dbSchema) {
198
- var _a, _b;
199
- const insertIntoTable = select_columns_1.splitName(insertStatement.tableRef().text).name;
200
- const fields = (_b = (_a = insertStatement.insertFromConstructor()) === null || _a === void 0 ? void 0 : _a.fields()) === null || _b === void 0 ? void 0 : _b.insertIdentifier().map(insertIdentifier => {
201
- const colRef = insertIdentifier.columnRef();
202
- if (colRef) {
203
- const fieldName = select_columns_1.splitName(colRef.text);
204
- const column = select_columns_1.findColumn2(fieldName, insertIntoTable, dbSchema);
205
- return column;
206
- }
207
- throw Error('Invalid sql');
208
- });
209
- //check insert stmt without fields (only values). Ex.: insert into mytable values()
210
- if (!fields) {
211
- return dbSchema.filter(column => column.table == insertIntoTable);
212
- }
213
- return fields;
214
- }
215
- exports.getInsertColumns = getInsertColumns;
216
- function getUpdateColumns(updateStatement, dbSchema) {
217
- const insertIntoTable = select_columns_1.splitName(updateStatement.tableReferenceList().tableReference()[0].text).name;
218
- const columns = dbSchema
219
- .filter(col => col.table == insertIntoTable)
220
- .map(col => {
221
- const colDef = {
222
- table: col.table,
223
- column: col.column,
224
- columnName: col.column,
225
- columnType: col.column_type,
226
- columnKey: col.columnKey,
227
- notNull: col.notNull,
228
- tableAlias: ''
229
- };
230
- return colDef;
231
- });
232
- return columns;
233
- }
234
- exports.getUpdateColumns = getUpdateColumns;
235
- function getDeleteColumns(deleteStatement, dbSchema) {
236
- var _a, _b;
237
- const tableNameStr = (_a = deleteStatement.tableRef()) === null || _a === void 0 ? void 0 : _a.text;
238
- const tableAlias = (_b = deleteStatement.tableAlias()) === null || _b === void 0 ? void 0 : _b.text;
239
- const tableName = select_columns_1.splitName(tableNameStr).name;
240
- const columns = dbSchema
241
- .filter(col => col.table == tableName)
242
- .map(col => {
243
- const colDef = {
244
- table: col.table,
245
- column: col.column,
246
- columnName: col.column,
247
- columnType: col.column_type,
248
- columnKey: col.columnKey,
249
- notNull: col.notNull,
250
- tableAlias: tableAlias
251
- };
252
- return colDef;
253
- });
254
- return columns;
255
- }
256
- exports.getDeleteColumns = getDeleteColumns;
257
- function analiseSelectStatement(selectStatement, dbSchema, namedParameters) {
258
- const querySpec = parse_1.getQuerySpecificationsFromSelectStatement(selectStatement);
259
- const fromColumns = select_columns_1.getColumnsFrom(querySpec[0], dbSchema);
260
- let result = analiseQuerySpecification(querySpec[0], dbSchema, namedParameters, fromColumns);
261
- for (let index = 1; index < querySpec.length; index++) {
262
- const unionQuery = querySpec[index];
263
- const fromColumns2 = select_columns_1.getColumnsFrom(unionQuery, dbSchema);
264
- const result2 = analiseQuerySpecification(unionQuery, dbSchema, namedParameters, fromColumns2);
265
- result = unionResult(result, result2);
266
- }
267
- return result;
268
- }
269
- exports.analiseSelectStatement = analiseSelectStatement;
270
- function unionResult(typeInference1, typeInference2) {
271
- const resultColumnTypes = typeInference1.columns.map((col1, index) => {
272
- const col2 = typeInference2.columns[index];
273
- const resultType = unionTypeResult(col1, col2);
274
- return resultType;
275
- });
276
- return {
277
- columns: resultColumnTypes,
278
- parameters: [...typeInference1.parameters, ...typeInference2.parameters] //TODO-INVERSE?
279
- };
280
- }
281
- function unionTypeResult(type1, type2) {
282
- const typeOrder = ['tinyint', 'smallint', 'mediumint', 'int', 'bigint', 'float', 'double', 'varchar'];
283
- const indexType1 = typeOrder.indexOf(type1);
284
- const indexType2 = typeOrder.indexOf(type2);
285
- const max = Math.max(indexType1, indexType2);
286
- return typeOrder[max];
287
- }
288
- exports.unionTypeResult = unionTypeResult;
289
- function analiseQuerySpecification(querySpec, dbSchema, namedParameters, fromColumns) {
290
- const context = {
291
- dbSchema,
292
- parameters: [],
293
- constraints: [],
294
- fromColumns: fromColumns
295
- };
296
- const queryTypes = walkQuerySpecification(context, querySpec);
297
- const paramIndexes = util_1.getParameterIndexes(namedParameters); //for [a, a, b, a] will return a: [0, 1, 3]; b: [2]
298
- paramIndexes.forEach(paramIndex => {
299
- util_1.getPairWise(paramIndex.indexes, (cur, next) => {
300
- context.constraints.push({
301
- expression: paramIndex.paramName,
302
- type1: context.parameters[cur],
303
- type2: context.parameters[next]
304
- });
305
- });
306
- });
307
- // console.log("namedNodes");
308
- // console.dir(namedNodes, { depth: null });
309
- // console.log("constraints2=");
310
- // console.dir(constraints, { depth: null });
311
- const substitutions = {};
312
- unify_1.unify(context.constraints, substitutions);
313
- const parameters = context.parameters.map(param => getVarType(substitutions, param));
314
- const columnTypes = queryTypes.types.map(param => getVarType(substitutions, param));
315
- const querySpecResult = {
316
- parameters: parameters,
317
- columns: columnTypes
318
- };
319
- return querySpecResult;
320
- }
321
- exports.analiseQuerySpecification = analiseQuerySpecification;
322
- function generateTypeInfo(namedNodes, constraints) {
323
- const substitutions = {};
324
- unify_1.unify(constraints, substitutions);
325
- const parameters = namedNodes.map(param => getVarType(substitutions, param));
326
- return parameters;
327
- }
328
- exports.generateTypeInfo = generateTypeInfo;
329
- function getVarType(substitutions, typeVar) {
330
- if (typeVar.kind == 'TypeVar') {
331
- const type = substitutions[typeVar.id];
332
- if (!type) {
333
- return typeVar.type;
334
- }
335
- const resultType = typeVar.list ? type.type + '[]' : type.type;
336
- return resultType;
337
- }
338
- return '?';
339
- }
340
- function walkQuerySpecification(context, querySpec) {
341
- const listType = [];
342
- if (querySpec.selectItemList().MULT_OPERATOR()) {
343
- context.fromColumns.forEach(col => {
344
- const colType = freshVar(col.columnName, col.columnType);
345
- listType.push(colType);
346
- });
347
- }
348
- querySpec.selectItemList().selectItem().forEach(selectItem => {
349
- const tableWild = selectItem.tableWild(); //ex. t1.*
350
- if (tableWild === null || tableWild === void 0 ? void 0 : tableWild.MULT_OPERATOR()) {
351
- tableWild.identifier().forEach(tabWild => {
352
- const prefix = tabWild.text;
353
- const columns = select_columns_1.selectAllColumns(prefix, context.fromColumns);
354
- columns.forEach(col => {
355
- const colType = freshVar(col.columnName, col.columnType);
356
- listType.push(colType);
357
- });
358
- });
359
- }
360
- else {
361
- const expr = selectItem.expr();
362
- if (expr) {
363
- const exprType = walkExpr(context, expr);
364
- if (exprType.kind == 'TypeOperator') {
365
- const subqueryType = exprType.types[0];
366
- listType.push(subqueryType);
367
- }
368
- else {
369
- listType.push(exprType);
370
- }
371
- }
372
- }
373
- });
374
- const typeOperator = {
375
- kind: 'TypeOperator',
376
- selectItem: true,
377
- types: listType
378
- };
379
- const fromClause = querySpec.fromClause();
380
- if (fromClause) {
381
- walkFromClause(context, fromClause);
382
- }
383
- const whereClause = querySpec.whereClause();
384
- //TODO - HAVING, BLAH
385
- if (whereClause) {
386
- const whereExpr = whereClause === null || whereClause === void 0 ? void 0 : whereClause.expr();
387
- walkExpr(context, whereExpr);
388
- }
389
- return typeOperator;
390
- }
391
- exports.walkQuerySpecification = walkQuerySpecification;
392
- function walkFromClause(context, fromClause) {
393
- var _a;
394
- const tableReferences = (_a = fromClause.tableReferenceList()) === null || _a === void 0 ? void 0 : _a.tableReference();
395
- tableReferences === null || tableReferences === void 0 ? void 0 : tableReferences.forEach(tabeRef => {
396
- tabeRef.joinedTable().forEach(joinedTable => {
397
- const onExpr = joinedTable.expr();
398
- if (onExpr) {
399
- walkExpr(context, onExpr);
400
- }
401
- });
402
- });
403
- }
404
- function walkExpr(context, expr) {
405
- if (expr instanceof ts_mysql_parser_1.ExprIsContext) {
406
- const boolPri = expr.boolPri();
407
- const boolPriType = walkBoolPri(context, boolPri);
408
- return boolPriType;
409
- }
410
- if (expr instanceof ts_mysql_parser_1.ExprNotContext) {
411
- return freshVar(expr.text, 'tinyint');
412
- ;
413
- }
414
- if (expr instanceof ts_mysql_parser_1.ExprAndContext || expr instanceof ts_mysql_parser_1.ExprXorContext || expr instanceof ts_mysql_parser_1.ExprOrContext) {
415
- const exprLeft = expr.expr()[0];
416
- walkExpr(context, exprLeft);
417
- const exprRight = expr.expr()[1];
418
- walkExpr(context, exprRight);
419
- return freshVar(expr.text, 'tinyint');
420
- }
421
- throw Error('invalid type');
422
- }
423
- function walkBoolPri(context, boolPri) {
424
- if (boolPri instanceof ts_mysql_parser_1.PrimaryExprPredicateContext) {
425
- const predicate = boolPri.predicate();
426
- const predicateType = walkPredicate(context, predicate);
427
- return predicateType;
428
- }
429
- if (boolPri instanceof ts_mysql_parser_1.PrimaryExprIsNullContext) {
430
- const boolPri2 = boolPri.boolPri();
431
- walkBoolPri(context, boolPri2);
432
- return freshVar(boolPri.text, '?');
433
- }
434
- if (boolPri instanceof ts_mysql_parser_1.PrimaryExprCompareContext) {
435
- const compareLeft = boolPri.boolPri();
436
- const compareRight = boolPri.predicate();
437
- const typeLeft = walkBoolPri(context, compareLeft);
438
- const typeRight = walkPredicate(context, compareRight);
439
- context.constraints.push({
440
- expression: boolPri.text,
441
- type1: typeLeft,
442
- type2: typeRight
443
- });
444
- return freshVar(boolPri.text, 'tinyint');
445
- }
446
- if (boolPri instanceof ts_mysql_parser_1.PrimaryExprAllAnyContext) {
447
- const compareLeft = boolPri.boolPri();
448
- const compareRight = boolPri.subquery();
449
- const typeLeft = walkBoolPri(context, compareLeft);
450
- const typeRight = walkSubquery(context, compareRight);
451
- context.constraints.push({
452
- expression: boolPri.text,
453
- type1: typeLeft,
454
- type2: typeRight
455
- });
456
- return freshVar(boolPri.text, 'tinyint');
457
- }
458
- throw Error('invalid sql');
459
- }
460
- function walkPredicate(context, predicate) {
461
- const bitExpr = predicate.bitExpr()[0];
462
- const bitExprType = walkBitExpr(context, bitExpr);
463
- const predicateOperations = predicate.predicateOperations();
464
- if (predicateOperations) {
465
- const rightType = walkpredicateOperations(context, bitExprType, predicateOperations);
466
- context.constraints.push({
467
- expression: predicateOperations.text,
468
- type1: bitExprType,
469
- type2: rightType,
470
- mostGeneralType: true
471
- });
472
- return rightType;
473
- }
474
- // return freshVar(predicateOperations.text, 'tinyint');
475
- return bitExprType;
476
- }
477
- function walkpredicateOperations(context, parentType, predicateOperations) {
478
- if (predicateOperations instanceof ts_mysql_parser_1.PredicateExprInContext) {
479
- const subquery = predicateOperations.subquery();
480
- if (subquery) {
481
- const rightType = walkSubquery(context, subquery);
482
- return rightType;
483
- }
484
- const exprList = predicateOperations.exprList();
485
- if (exprList) {
486
- const rightType = walkExprList(context, exprList);
487
- return rightType;
488
- }
489
- }
490
- if (predicateOperations instanceof ts_mysql_parser_1.PredicateExprLikeContext) {
491
- const simpleExpr = predicateOperations.simpleExpr()[0];
492
- const rightType = walkSimpleExpr(context, simpleExpr);
493
- context.constraints.push({
494
- expression: simpleExpr.text,
495
- type1: parentType,
496
- type2: rightType
497
- });
498
- return rightType;
499
- }
500
- throw Error("Not expected");
501
- }
502
- function walkExprList(context, exprList) {
503
- const listType = exprList.expr().map(item => {
504
- const exprType = walkExpr(context, item);
505
- return exprType;
506
- });
507
- const type = {
508
- kind: 'TypeOperator',
509
- types: listType
510
- };
511
- return type;
512
- }
513
- function walkBitExpr(context, bitExpr) {
514
- const simpleExpr = bitExpr.simpleExpr();
515
- if (simpleExpr) {
516
- return walkSimpleExpr(context, simpleExpr);
517
- }
518
- if (bitExpr.bitExpr().length == 2) {
519
- const bitExprType = freshVar(bitExpr.text, 'number');
520
- const bitExprLeft = bitExpr.bitExpr()[0];
521
- const typeLeftTemp = walkBitExpr(context, bitExprLeft);
522
- const typeLeft = typeLeftTemp.kind == 'TypeOperator' ? typeLeftTemp.types[0] : typeLeftTemp;
523
- //const newTypeLeft = typeLeft.name == '?'? freshVar('?', 'bigint') : typeLeft;
524
- const bitExprRight = bitExpr.bitExpr()[1];
525
- const typeRightTemp = walkBitExpr(context, bitExprRight);
526
- //In the expression 'id + (value + 2) + ?' the '(value+2)' is treated as a SimpleExprListContext and return a TypeOperator
527
- const typeRight = typeRightTemp.kind == 'TypeOperator' ? typeRightTemp.types[0] : typeRightTemp;
528
- //const newTypeRight = typeRight.name == '?'? freshVar('?', 'bigint') : typeRight;
529
- context.constraints.push({
530
- expression: bitExpr.text,
531
- type1: typeLeft,
532
- type2: typeRight,
533
- mostGeneralType: true,
534
- coercionType: 'Sum'
535
- });
536
- context.constraints.push({
537
- expression: bitExpr.text,
538
- type1: bitExprType,
539
- type2: typeLeft,
540
- mostGeneralType: true,
541
- coercionType: 'Sum'
542
- });
543
- context.constraints.push({
544
- expression: bitExpr.text,
545
- type1: bitExprType,
546
- type2: typeRight,
547
- mostGeneralType: true,
548
- coercionType: 'Sum'
549
- });
550
- return bitExprType;
551
- }
552
- if (bitExpr.INTERVAL_SYMBOL()) {
553
- const bitExpr2 = bitExpr.bitExpr()[0];
554
- const leftType = walkBitExpr(context, bitExpr2);
555
- const expr = bitExpr.expr(); //expr interval
556
- walkExpr(context, expr);
557
- context.constraints.push({
558
- expression: bitExpr.text,
559
- type1: leftType,
560
- type2: freshVar('datetime', 'datetime')
561
- });
562
- return freshVar('datetime', 'datetime');
563
- }
564
- throw Error('Invalid sql');
565
- }
566
- function walkSimpleExpr(context, simpleExpr) {
567
- var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p;
568
- if (simpleExpr instanceof ts_mysql_parser_1.SimpleExprColumnRefContext) {
569
- const fieldName = select_columns_1.splitName(simpleExpr.text);
570
- const columnType = select_columns_1.findColumn(fieldName, context.fromColumns).columnType;
571
- const type = freshVar(simpleExpr.text, columnType);
572
- return type;
573
- }
574
- if (simpleExpr instanceof ts_mysql_parser_1.SimpleExprRuntimeFunctionContext) {
575
- const runtimeFunctionCall = simpleExpr.runtimeFunctionCall();
576
- if (runtimeFunctionCall.NOW_SYMBOL()) {
577
- return freshVar(simpleExpr.text, 'datetime');
578
- }
579
- if (runtimeFunctionCall.CURDATE_SYMBOL()) {
580
- return freshVar(simpleExpr.text, 'date');
581
- }
582
- if (runtimeFunctionCall.CURTIME_SYMBOL()) {
583
- return freshVar(simpleExpr.text, 'time');
584
- }
585
- if (runtimeFunctionCall.REPLACE_SYMBOL()) {
586
- const exprList = runtimeFunctionCall.expr();
587
- exprList.forEach(expr => {
588
- const exprType = walkExpr(context, expr);
589
- context.constraints.push({
590
- expression: expr.text,
591
- type1: exprType,
592
- type2: freshVar('varchar', 'varchar')
593
- });
594
- });
595
- return freshVar('varchar', 'varchar');
596
- }
597
- if (runtimeFunctionCall.YEAR_SYMBOL() || runtimeFunctionCall.MONTH_SYMBOL() || runtimeFunctionCall.DAY_SYMBOL()) {
598
- const expr = (_a = runtimeFunctionCall.exprWithParentheses()) === null || _a === void 0 ? void 0 : _a.expr();
599
- if (expr) {
600
- const paramType = walkExpr(context, expr);
601
- if (paramType.kind == 'TypeVar' && isDateTimeLiteral(paramType.name)) {
602
- paramType.type = 'datetime';
603
- }
604
- if (paramType.kind == 'TypeVar' && isDateLiteral(paramType.name)) {
605
- paramType.type = 'date';
606
- }
607
- context.constraints.push({
608
- expression: expr.text,
609
- type1: paramType,
610
- type2: freshVar(simpleExpr.text, 'date')
611
- });
612
- }
613
- const returnType = runtimeFunctionCall.YEAR_SYMBOL() ? 'year' : 'tinyint';
614
- return freshVar(simpleExpr.text, returnType);
615
- }
616
- if (runtimeFunctionCall.HOUR_SYMBOL() || runtimeFunctionCall.MINUTE_SYMBOL() || runtimeFunctionCall.SECOND_SYMBOL()) {
617
- const expr = (_b = runtimeFunctionCall.exprWithParentheses()) === null || _b === void 0 ? void 0 : _b.expr();
618
- if (expr) {
619
- const paramType = walkExpr(context, expr);
620
- if (paramType.kind == 'TypeVar' && isTimeLiteral(paramType.name)) {
621
- paramType.type = 'time';
622
- }
623
- if (paramType.kind == 'TypeVar' && isDateLiteral(paramType.name)) {
624
- paramType.type = 'date';
625
- }
626
- if (paramType.kind == 'TypeVar' && isDateTimeLiteral(paramType.name)) {
627
- paramType.type = 'datetime';
628
- }
629
- context.constraints.push({
630
- expression: expr.text,
631
- type1: paramType,
632
- type2: freshVar(simpleExpr.text, 'time')
633
- });
634
- }
635
- //HOUR can return values greater than 23. Ex.: SELECT HOUR('272:59:59');
636
- //https://dev.mysql.com/doc/refman/8.0/en/date-and-time-functions.html#function_hour
637
- const returnType = runtimeFunctionCall.HOUR_SYMBOL() ? 'int' : 'tinyint';
638
- return freshVar(simpleExpr.text, returnType);
639
- }
640
- const trimFunction = runtimeFunctionCall.trimFunction();
641
- if (trimFunction) {
642
- const exprList = trimFunction.expr();
643
- if (exprList.length == 1) {
644
- const exprType = walkExpr(context, exprList[0]);
645
- context.constraints.push({
646
- expression: exprList[0].text,
647
- type1: exprType,
648
- type2: freshVar('varchar', 'varchar')
649
- });
650
- }
651
- if (exprList.length == 2) {
652
- const exprType = walkExpr(context, exprList[0]);
653
- const expr2Type = walkExpr(context, exprList[1]);
654
- context.constraints.push({
655
- expression: exprList[0].text,
656
- type1: exprType,
657
- type2: freshVar('varchar', 'varchar')
658
- });
659
- context.constraints.push({
660
- expression: exprList[1].text,
661
- type1: expr2Type,
662
- type2: freshVar('varchar', 'varchar')
663
- });
664
- }
665
- return freshVar('varchar', 'varchar');
666
- }
667
- const substringFunction = runtimeFunctionCall.substringFunction();
668
- if (substringFunction) {
669
- const exprList = substringFunction.expr();
670
- const varcharParam = freshVar('varchar', 'varchar');
671
- const intParam = freshVar('int', 'int');
672
- const params = {
673
- kind: 'FixedLengthParams',
674
- paramsType: [varcharParam, intParam, intParam]
675
- };
676
- walkExprListParameters(context, exprList, params);
677
- return varcharParam;
678
- }
679
- if (runtimeFunctionCall.ADDDATE_SYMBOL()
680
- || runtimeFunctionCall.DATE_ADD_SYMBOL()
681
- || runtimeFunctionCall.SUBDATE_SYMBOL()
682
- || runtimeFunctionCall.DATE_SUB_SYMBOL()) {
683
- //SELECT ADDDATE('2008-01-02', INTERVAL 31 DAY)
684
- //SELECT ADDDATE('2008-01-02', 31)
685
- const expr1 = runtimeFunctionCall.expr()[0];
686
- const expr2 = runtimeFunctionCall.expr()[1];
687
- const typeExpr1 = walkExpr(context, expr1);
688
- const typeExpr2 = walkExpr(context, expr2);
689
- if (typeExpr1.kind == 'TypeVar' && (isDateLiteral(typeExpr1.name) || isDateTimeLiteral(typeExpr1.name))) {
690
- typeExpr1.type = 'datetime';
691
- }
692
- context.constraints.push({
693
- expression: expr1.text,
694
- type1: typeExpr1,
695
- type2: freshVar('datetime', 'datetime')
696
- });
697
- context.constraints.push({
698
- expression: expr2.text,
699
- type1: typeExpr2,
700
- type2: freshVar('bigint', 'bigint')
701
- });
702
- return freshVar('datetime', 'datetime');
703
- }
704
- if (runtimeFunctionCall.COALESCE_SYMBOL()) {
705
- const exprList = (_c = runtimeFunctionCall.exprListWithParentheses()) === null || _c === void 0 ? void 0 : _c.exprList().expr();
706
- if (exprList) {
707
- const paramType = freshVar('?', '?');
708
- const params = {
709
- kind: 'VariableLengthParams',
710
- paramType: 'any'
711
- };
712
- const paramsTypeList = walkExprListParameters(context, exprList, params);
713
- paramsTypeList.forEach((typeVar, paramIndex) => {
714
- context.constraints.push({
715
- expression: runtimeFunctionCall.text + '_param' + (paramIndex + 1),
716
- type1: paramType,
717
- type2: typeVar,
718
- mostGeneralType: true,
719
- coercionType: 'Coalesce'
720
- });
721
- });
722
- return paramType;
723
- }
724
- }
725
- //MOD (number, number): number
726
- if (runtimeFunctionCall.MOD_SYMBOL()) {
727
- const functionType = freshVar('number', 'number');
728
- const exprList = runtimeFunctionCall.expr();
729
- const param1 = walkExpr(context, exprList[0]);
730
- const param2 = walkExpr(context, exprList[1]);
731
- context.constraints.push({
732
- expression: simpleExpr.text,
733
- type1: freshVar('number', 'number'),
734
- type2: param1,
735
- mostGeneralType: true
736
- });
737
- context.constraints.push({
738
- expression: simpleExpr.text,
739
- type1: freshVar('number', 'number'),
740
- type2: param2,
741
- mostGeneralType: true
742
- });
743
- context.constraints.push({
744
- expression: simpleExpr.text,
745
- type1: functionType,
746
- type2: param1,
747
- mostGeneralType: true
748
- });
749
- context.constraints.push({
750
- expression: simpleExpr.text,
751
- type1: functionType,
752
- type2: param2,
753
- mostGeneralType: true
754
- });
755
- return functionType;
756
- }
757
- throw Error('Function not supported: ' + runtimeFunctionCall.text);
758
- }
759
- if (simpleExpr instanceof ts_mysql_parser_1.SimpleExprFunctionContext) {
760
- const functionIdentifier = getFunctionName(simpleExpr);
761
- if (functionIdentifier === 'concat_ws' || (functionIdentifier === null || functionIdentifier === void 0 ? void 0 : functionIdentifier.toLowerCase()) === 'concat') {
762
- const varcharType = freshVar(simpleExpr.text, 'varchar');
763
- const params = {
764
- kind: 'VariableLengthParams',
765
- paramType: '?'
766
- };
767
- walkFunctionParameters(context, simpleExpr, params);
768
- return varcharType;
769
- }
770
- if (functionIdentifier === 'avg') {
771
- const functionType = freshVar(simpleExpr.text, '?');
772
- context.constraints.push({
773
- expression: simpleExpr.text,
774
- type1: functionType,
775
- type2: freshVar('decimal', 'decimal'),
776
- mostGeneralType: true
777
- });
778
- const params = {
779
- kind: 'FixedLengthParams',
780
- paramsType: [functionType]
781
- };
782
- walkFunctionParameters(context, simpleExpr, params);
783
- return functionType;
784
- }
785
- if (functionIdentifier === 'round') {
786
- const functionType = freshVar(simpleExpr.text, '?');
787
- const params = {
788
- kind: 'FixedLengthParams',
789
- paramsType: [functionType]
790
- };
791
- const paramsType = walkFunctionParameters(context, simpleExpr, params);
792
- //The return value has the same type as the first argument
793
- context.constraints.push({
794
- expression: simpleExpr.text,
795
- type1: functionType,
796
- type2: paramsType[0],
797
- mostGeneralType: true
798
- });
799
- return functionType;
800
- }
801
- if (functionIdentifier === 'floor') {
802
- const doubleParam = freshVar('double', 'double');
803
- const params = {
804
- kind: 'FixedLengthParams',
805
- paramsType: [doubleParam, doubleParam]
806
- };
807
- walkFunctionParameters(context, simpleExpr, params);
808
- return freshVar(simpleExpr.text, 'bigint');
809
- }
810
- if (functionIdentifier === 'str_to_date') {
811
- const varcharParam = freshVar('varchar', 'varchar');
812
- const params = {
813
- kind: 'FixedLengthParams',
814
- paramsType: [varcharParam, varcharParam]
815
- };
816
- walkFunctionParameters(context, simpleExpr, params);
817
- return freshVar(simpleExpr.text, 'date');
818
- }
819
- if (functionIdentifier === 'datediff') {
820
- const udfExprList = (_d = simpleExpr.functionCall().udfExprList()) === null || _d === void 0 ? void 0 : _d.udfExpr();
821
- if (udfExprList) {
822
- udfExprList.forEach((inExpr) => {
823
- const expr = inExpr.expr();
824
- const exprType = walkExpr(context, expr);
825
- const newType = verifyDateTypesCoercion(exprType);
826
- context.constraints.push({
827
- expression: expr.text,
828
- type1: newType,
829
- type2: freshVar('date', 'date'),
830
- mostGeneralType: true
831
- });
832
- });
833
- }
834
- return freshVar(simpleExpr.text, 'bigint');
835
- }
836
- if (functionIdentifier === 'lpad' || functionIdentifier == 'rpad') {
837
- const varcharParam = freshVar('varchar', 'varchar');
838
- const intParam = freshVar('int', 'int');
839
- const params = {
840
- kind: 'FixedLengthParams',
841
- paramsType: [varcharParam, intParam, varcharParam]
842
- };
843
- walkFunctionParameters(context, simpleExpr, params);
844
- return varcharParam;
845
- }
846
- if (functionIdentifier === 'lower'
847
- || functionIdentifier === 'lcase'
848
- || functionIdentifier === 'upper'
849
- || functionIdentifier === 'ucase'
850
- || functionIdentifier === 'ltrim'
851
- || functionIdentifier === 'rtrim') {
852
- const varcharParam = freshVar('varchar', 'varchar');
853
- const params = {
854
- kind: 'FixedLengthParams',
855
- paramsType: [varcharParam]
856
- };
857
- walkFunctionParameters(context, simpleExpr, params);
858
- return varcharParam;
859
- }
860
- if (functionIdentifier === 'length' || functionIdentifier == 'char_length') {
861
- const varcharParam = freshVar('varchar', 'varchar');
862
- const params = {
863
- kind: 'FixedLengthParams',
864
- paramsType: [varcharParam]
865
- };
866
- walkFunctionParameters(context, simpleExpr, params);
867
- return freshVar('int', 'int');
868
- }
869
- if (functionIdentifier === 'abs') {
870
- const functionType = freshVar('number', 'number');
871
- const udfExprList = (_e = simpleExpr.functionCall().udfExprList()) === null || _e === void 0 ? void 0 : _e.udfExpr();
872
- udfExprList === null || udfExprList === void 0 ? void 0 : udfExprList.forEach(expr => {
873
- const param1 = walkExpr(context, expr.expr());
874
- context.constraints.push({
875
- expression: simpleExpr.text,
876
- type1: functionType,
877
- type2: param1,
878
- mostGeneralType: true
879
- });
880
- });
881
- return functionType;
882
- }
883
- if (functionIdentifier == 'ceiling' || functionIdentifier == 'ceil') {
884
- const functionType = freshVar('number', 'number');
885
- const udfExprList = (_f = simpleExpr.functionCall().udfExprList()) === null || _f === void 0 ? void 0 : _f.udfExpr();
886
- udfExprList === null || udfExprList === void 0 ? void 0 : udfExprList.forEach(expr => {
887
- const param1 = walkExpr(context, expr.expr());
888
- context.constraints.push({
889
- expression: simpleExpr.text,
890
- type1: functionType,
891
- type2: param1,
892
- mostGeneralType: true,
893
- coercionType: 'Ceiling'
894
- });
895
- });
896
- return functionType;
897
- }
898
- if (functionIdentifier == 'timestampdiff') {
899
- const udfExprList = (_g = simpleExpr.functionCall().udfExprList()) === null || _g === void 0 ? void 0 : _g.udfExpr();
900
- if (udfExprList) {
901
- const [first, ...rest] = udfExprList;
902
- const unit = first.text.trim().toLowerCase();
903
- rest.forEach((inExpr, paramIndex) => {
904
- const expr = inExpr.expr();
905
- const exprType = walkExpr(context, expr);
906
- const newType = verifyDateTypesCoercion(exprType);
907
- //const expectedType = ['hour', 'minute', 'second'].includes(unit)? 'time' : 'datetime'
908
- context.constraints.push({
909
- expression: expr.text,
910
- type1: newType,
911
- type2: freshVar('datetime', 'datetime'),
912
- mostGeneralType: true
913
- });
914
- });
915
- }
916
- return freshVar('int', 'int');
917
- }
918
- if (functionIdentifier == 'ifnull') {
919
- const functionType = freshVar(simpleExpr.text, '?');
920
- const udfExprList = (_h = simpleExpr.functionCall().udfExprList()) === null || _h === void 0 ? void 0 : _h.udfExpr();
921
- if (udfExprList) {
922
- const [expr1, expr2] = udfExprList;
923
- walkExpr(context, expr1.expr());
924
- const expr2Type = walkExpr(context, expr2.expr());
925
- context.constraints.push({
926
- expression: simpleExpr.text,
927
- type1: functionType,
928
- type2: expr2Type
929
- });
930
- }
931
- return functionType;
932
- }
933
- throw Error('Function not supported: ' + functionIdentifier); //TODO ifnull
934
- }
935
- if (simpleExpr instanceof ts_mysql_parser_1.SimpleExprParamMarkerContext) {
936
- const param = freshVar('?', '?');
937
- context.parameters.push(param);
938
- return param;
939
- }
940
- if (simpleExpr instanceof ts_mysql_parser_1.SimpleExprSumContext) {
941
- if (simpleExpr.sumExpr().MAX_SYMBOL() || simpleExpr.sumExpr().MIN_SYMBOL()) {
942
- const functionType = freshVar(simpleExpr.text, '?');
943
- const inSumExpr = (_j = simpleExpr.sumExpr().inSumExpr()) === null || _j === void 0 ? void 0 : _j.expr();
944
- if (inSumExpr) {
945
- const inSumExprType = walkExpr(context, inSumExpr);
946
- context.constraints.push({
947
- expression: simpleExpr.text,
948
- type1: functionType,
949
- type2: inSumExprType,
950
- mostGeneralType: true
951
- });
952
- }
953
- return functionType;
954
- }
955
- if (simpleExpr.sumExpr().COUNT_SYMBOL()) {
956
- const functionType = freshVar(simpleExpr.text, 'bigint');
957
- const inSumExpr = (_k = simpleExpr.sumExpr().inSumExpr()) === null || _k === void 0 ? void 0 : _k.expr();
958
- if (inSumExpr) {
959
- walkExpr(context, inSumExpr);
960
- }
961
- return functionType;
962
- }
963
- if (simpleExpr.sumExpr().SUM_SYMBOL() || simpleExpr.sumExpr().AVG_SYMBOL()) {
964
- const functionType = freshVar(simpleExpr.text, '?');
965
- const inSumExpr = (_l = simpleExpr.sumExpr().inSumExpr()) === null || _l === void 0 ? void 0 : _l.expr();
966
- if (inSumExpr) {
967
- const inSumExprType = walkExpr(context, inSumExpr);
968
- context.constraints.push({
969
- expression: simpleExpr.text,
970
- type1: functionType,
971
- type2: inSumExprType,
972
- mostGeneralType: true,
973
- coercionType: 'SumFunction'
974
- });
975
- }
976
- return functionType;
977
- }
978
- }
979
- if (simpleExpr instanceof ts_mysql_parser_1.SimpleExprLiteralContext) {
980
- const literal = simpleExpr.literal();
981
- if (literal.textLiteral()) {
982
- const text = ((_m = literal.textLiteral()) === null || _m === void 0 ? void 0 : _m.text.slice(1, -1)) || ''; //remove quotes
983
- return freshVar(text, 'varchar');
984
- }
985
- const numLiteral = literal.numLiteral();
986
- if (numLiteral) {
987
- return freshVar(numLiteral.text, 'bigint');
988
- // addNamedNode(simpleExpr, freshVar('bigint', 'bigint'), namedNodes)
989
- // if(numLiteral.INT_NUMBER()) {
990
- // const typeInt = freshVar('int', 'int');
991
- // addNamedNode(simpleExpr, typeInt, namedNodes)
992
- // }
993
- // if(numLiteral.DECIMAL_NUMBER()) {
994
- // const typeDecimal = freshVar('decimal', 'decimal');
995
- // addNamedNode(simpleExpr, typeDecimal, namedNodes)
996
- // }
997
- // if(numLiteral.FLOAT_NUMBER()) {
998
- // const typeFloat = freshVar('float', 'float');
999
- // addNamedNode(simpleExpr, typeFloat, namedNodes)
1000
- // }
1001
- ;
1002
- }
1003
- const boolLiteral = literal.boolLiteral();
1004
- if (boolLiteral) {
1005
- return freshVar(boolLiteral.text, 'bit');
1006
- }
1007
- const nullLiteral = literal.nullLiteral();
1008
- if (nullLiteral) {
1009
- return freshVar(nullLiteral.text, '?');
1010
- }
1011
- throw Error('literal not supported:' + literal.text);
1012
- //...
1013
- }
1014
- if (simpleExpr instanceof ts_mysql_parser_1.SimpleExprListContext) {
1015
- const exprList = simpleExpr.exprList();
1016
- const listType = exprList.expr().map(item => {
1017
- const exprType = walkExpr(context, item);
1018
- return exprType;
1019
- });
1020
- const resultType = {
1021
- kind: 'TypeOperator',
1022
- types: listType
1023
- };
1024
- return resultType;
1025
- }
1026
- if (simpleExpr instanceof ts_mysql_parser_1.SimpleExprSubQueryContext) {
1027
- const subquery = simpleExpr.subquery();
1028
- const subqueryType = walkSubquery(context, subquery);
1029
- return subqueryType;
1030
- }
1031
- if (simpleExpr instanceof ts_mysql_parser_1.SimpleExprCaseContext) {
1032
- //case when expr then expr else expr
1033
- const caseType = freshVar(simpleExpr.text, '?');
1034
- simpleExpr.whenExpression().forEach(whenExprCont => {
1035
- const whenExpr = whenExprCont.expr();
1036
- const whenType = walkExpr(context, whenExpr);
1037
- context.constraints.push({
1038
- expression: whenExpr.text,
1039
- type1: whenType.kind == 'TypeOperator' ? whenType.types[0] : whenType,
1040
- type2: freshVar('tinyint', 'tinyint') //bool
1041
- });
1042
- });
1043
- const thenTypes = simpleExpr.thenExpression().map(thenExprCtx => {
1044
- const thenExpr = thenExprCtx.expr();
1045
- const thenType = walkExpr(context, thenExpr);
1046
- context.constraints.push({
1047
- expression: thenExprCtx.text,
1048
- type1: caseType,
1049
- type2: thenType.kind == 'TypeOperator' ? thenType.types[0] : thenType,
1050
- mostGeneralType: true,
1051
- });
1052
- return thenType;
1053
- });
1054
- const elseExpr = (_o = simpleExpr.elseExpression()) === null || _o === void 0 ? void 0 : _o.expr();
1055
- if (elseExpr) {
1056
- const elseType = walkExpr(context, elseExpr);
1057
- context.constraints.push({
1058
- expression: (_p = simpleExpr.elseExpression()) === null || _p === void 0 ? void 0 : _p.text,
1059
- type1: caseType,
1060
- type2: elseType.kind == 'TypeOperator' ? elseType.types[0] : elseType,
1061
- mostGeneralType: true
1062
- });
1063
- thenTypes.forEach(thenType => {
1064
- var _a;
1065
- context.constraints.push({
1066
- expression: (_a = simpleExpr.elseExpression()) === null || _a === void 0 ? void 0 : _a.text,
1067
- type1: thenType,
1068
- type2: elseType.kind == 'TypeOperator' ? elseType.types[0] : elseType,
1069
- mostGeneralType: true
1070
- });
1071
- });
1072
- }
1073
- return caseType;
1074
- }
1075
- if (simpleExpr instanceof ts_mysql_parser_1.SimpleExprIntervalContext) {
1076
- const exprList = simpleExpr.expr();
1077
- const exprLeft = exprList[0];
1078
- const exprRight = exprList[1];
1079
- const typeLeft = walkExpr(context, exprLeft);
1080
- const typeRight = walkExpr(context, exprRight);
1081
- context.constraints.push({
1082
- expression: exprLeft.text,
1083
- type1: typeLeft,
1084
- type2: freshVar('bigint', 'bigint')
1085
- });
1086
- if (typeRight.kind == 'TypeVar' && (isDateLiteral(typeRight.name) || isDateTimeLiteral(typeRight.name))) {
1087
- typeRight.type = 'datetime';
1088
- }
1089
- context.constraints.push({
1090
- expression: exprRight.text,
1091
- type1: typeRight,
1092
- type2: freshVar('datetime', 'datetime')
1093
- });
1094
- return freshVar('datetime', 'datetime');
1095
- }
1096
- throw Error('Invalid expression');
1097
- }
1098
- function verifyDateTypesCoercion(type) {
1099
- if (type.kind == 'TypeVar' && isDateTimeLiteral(type.name)) {
1100
- type.type = 'datetime';
1101
- }
1102
- if (type.kind == 'TypeVar' && isDateLiteral(type.name)) {
1103
- type.type = 'date';
1104
- }
1105
- if (type.kind == 'TypeVar' && isTimeLiteral(type.name)) {
1106
- type.type = 'time';
1107
- }
1108
- return type;
1109
- }
1110
- function isTimeLiteral(literal) {
1111
- return moment_1.default(literal, 'HH:mm:ss', true).isValid() || moment_1.default(literal, 'HH:mm', true).isValid();
1112
- }
1113
- function isDateTimeLiteral(literal) {
1114
- return moment_1.default(literal, 'YYYY-MM-DD HH:mm:ss', true).isValid();
1115
- }
1116
- function isDateLiteral(literal) {
1117
- return moment_1.default(literal, "YYYY-MM-DD", true).isValid();
1118
- }
1119
- function getFunctionName(simpleExprFunction) {
1120
- var _a, _b;
1121
- return ((_a = simpleExprFunction.functionCall().pureIdentifier()) === null || _a === void 0 ? void 0 : _a.text.toLowerCase()) || ((_b = simpleExprFunction.functionCall().qualifiedIdentifier()) === null || _b === void 0 ? void 0 : _b.text.toLowerCase());
1122
- }
1123
- function walkExprListParameters(context, exprList, params) {
1124
- return exprList.map((expr, paramIndex) => {
1125
- const exprType = walkExpr(context, expr);
1126
- const paramType = params.kind == 'FixedLengthParams' ? params.paramsType[paramIndex] : freshVar(params.paramType, params.paramType);
1127
- context.constraints.push({
1128
- expression: expr.text,
1129
- type1: exprType,
1130
- type2: paramType,
1131
- mostGeneralType: true
1132
- });
1133
- return paramType;
1134
- });
1135
- }
1136
- function walkFunctionParameters(context, simpleExprFunction, params) {
1137
- var _a, _b;
1138
- const functionName = getFunctionName(simpleExprFunction);
1139
- const udfExprList = (_a = simpleExprFunction.functionCall().udfExprList()) === null || _a === void 0 ? void 0 : _a.udfExpr();
1140
- if (udfExprList) {
1141
- const paramTypes = udfExprList
1142
- .filter((undefined, paramIndex) => {
1143
- return functionName == 'timestampdiff' ? paramIndex != 0 : true; //filter the first parameter of timestampdiff function
1144
- })
1145
- .map((inExpr, paramIndex) => {
1146
- const expr = inExpr.expr();
1147
- const exprType = walkExpr(context, expr);
1148
- context.constraints.push({
1149
- expression: expr.text,
1150
- type1: exprType,
1151
- type2: params.kind == 'FixedLengthParams' ? params.paramsType[paramIndex] : freshVar(params.paramType, params.paramType),
1152
- mostGeneralType: true
1153
- });
1154
- return exprType;
1155
- });
1156
- return paramTypes;
1157
- }
1158
- const exprList = (_b = simpleExprFunction.functionCall().exprList()) === null || _b === void 0 ? void 0 : _b.expr();
1159
- if (exprList) {
1160
- const paramTypes = exprList.map((inExpr, paramIndex) => {
1161
- const inSumExprType = walkExpr(context, inExpr);
1162
- context.constraints.push({
1163
- expression: inExpr.text,
1164
- type1: params.kind == 'FixedLengthParams' ? params.paramsType[paramIndex] : freshVar(params.paramType, params.paramType),
1165
- type2: inSumExprType,
1166
- mostGeneralType: true
1167
- });
1168
- return inSumExprType;
1169
- });
1170
- return paramTypes;
1171
- }
1172
- throw Error('Error in walkFunctionParameters');
1173
- }
1174
- function walkSubquery(context, queryExpressionParens) {
1175
- const querySpec = parse_1.getQuerySpecificationsFromSelectStatement(queryExpressionParens);
1176
- const subqueryColumns = select_columns_1.getColumnsFrom(querySpec[0], context.dbSchema);
1177
- const newContext = Object.assign(Object.assign({}, context), { fromColumns: context.fromColumns.concat(subqueryColumns) });
1178
- const typeInferResult = walkQuerySpecification(newContext, querySpec[0]);
1179
- for (let queryIndex = 1; queryIndex < querySpec.length; queryIndex++) { //union (if have any)
1180
- const unionColumns = select_columns_1.getColumnsFrom(querySpec[queryIndex], context.dbSchema);
1181
- const unionNewContext = Object.assign(Object.assign({}, context), { fromColumns: context.fromColumns.concat(unionColumns) });
1182
- const unionResult = walkQuerySpecification(unionNewContext, querySpec[queryIndex]);
1183
- typeInferResult.types.forEach((field, fieldIndex) => {
1184
- context.constraints.push({
1185
- expression: querySpec[queryIndex].text,
1186
- type1: typeInferResult.types[fieldIndex],
1187
- type2: unionResult.types[fieldIndex],
1188
- mostGeneralType: true
1189
- });
1190
- });
1191
- }
1192
- //Should retrun the union result type, not the first query from result
1193
- return typeInferResult;
1194
- }
1195
- exports.walkSubquery = walkSubquery;
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.walkSubquery = exports.walkQuerySpecification = exports.generateTypeInfo = exports.analiseQuerySpecification = exports.unionTypeResult = exports.analiseSelectStatement = exports.getDeleteColumns = exports.getUpdateColumns = exports.getInsertColumns = exports.analiseUpdateStatement = exports.analiseDeleteStatement = exports.analiseInsertStatement = exports.analiseTree = exports.freshVar = void 0;
7
+ const moment_1 = __importDefault(require("moment"));
8
+ const ts_mysql_parser_1 = require("ts-mysql-parser");
9
+ const select_columns_1 = require("./select-columns");
10
+ const parse_1 = require("./parse");
11
+ const unify_1 = require("./unify");
12
+ const infer_param_nullability_1 = require("./infer-param-nullability");
13
+ const describe_query_1 = require("../describe-query");
14
+ const util_1 = require("./util");
15
+ let counter = 0;
16
+ function freshVar(name, typeVar, selectItem, list) {
17
+ const param = {
18
+ kind: 'TypeVar',
19
+ id: ++counter,
20
+ name,
21
+ type: typeVar
22
+ };
23
+ if (list) {
24
+ param.list = true;
25
+ }
26
+ if (selectItem) {
27
+ param.selectItem = true;
28
+ }
29
+ return param;
30
+ }
31
+ exports.freshVar = freshVar;
32
+ function analiseTree(tree, dbSchema, namedParameters) {
33
+ var _a, _b, _c;
34
+ if (tree instanceof ts_mysql_parser_1.QueryContext) {
35
+ const selectStatement = (_a = tree.simpleStatement()) === null || _a === void 0 ? void 0 : _a.selectStatement();
36
+ if (selectStatement) {
37
+ return analiseSelectStatement(selectStatement, dbSchema, namedParameters);
38
+ }
39
+ const insertStatement = (_b = tree.simpleStatement()) === null || _b === void 0 ? void 0 : _b.insertStatement();
40
+ if (insertStatement) {
41
+ const insertStmt = analiseInsertStatement(insertStatement, dbSchema);
42
+ const TypeInfer = {
43
+ columns: [],
44
+ parameters: insertStmt.parameters.map(param => param.columnType)
45
+ };
46
+ return TypeInfer;
47
+ }
48
+ const updateStatement = (_c = tree.simpleStatement()) === null || _c === void 0 ? void 0 : _c.updateStatement();
49
+ if (updateStatement) {
50
+ const updateStmt = analiseUpdateStatement(updateStatement, dbSchema);
51
+ const TypeInfer = {
52
+ columns: [],
53
+ parameters: updateStmt.data.map(param => param.columnType)
54
+ };
55
+ return TypeInfer;
56
+ }
57
+ }
58
+ throw Error('invalid type of tree');
59
+ }
60
+ exports.analiseTree = analiseTree;
61
+ function analiseInsertStatement(insertStatement, dbSchema) {
62
+ const valuesContext = insertStatement.insertFromConstructor().insertValues().valueList().values()[0];
63
+ const insertColumns = getInsertColumns(insertStatement, dbSchema);
64
+ const allParameters = [];
65
+ const exprOrDefaultList = [];
66
+ valuesContext.DEFAULT_SYMBOL().forEach(terminalNode => {
67
+ exprOrDefaultList.push(terminalNode);
68
+ });
69
+ valuesContext.expr().forEach(expr => {
70
+ exprOrDefaultList.push(expr);
71
+ });
72
+ //order the tokens based on sql position
73
+ exprOrDefaultList.sort((token1, token2) => token1.sourceInterval.a - token2.sourceInterval.a);
74
+ exprOrDefaultList.forEach((expr, index) => {
75
+ const context = {
76
+ dbSchema,
77
+ constraints: [],
78
+ parameters: [],
79
+ fromColumns: []
80
+ };
81
+ const column = insertColumns[index];
82
+ if (expr instanceof ts_mysql_parser_1.ExprContext) {
83
+ const exprType = walkExpr(context, expr);
84
+ context.constraints.push({
85
+ expression: expr.text,
86
+ type1: freshVar(column.column, column.column_type),
87
+ type2: exprType.kind == 'TypeOperator' ? exprType.types[0] : exprType
88
+ });
89
+ }
90
+ const typeInfo = generateTypeInfo(context.parameters, context.constraints);
91
+ typeInfo.forEach(param => {
92
+ allParameters.push({
93
+ name: 'param' + (allParameters.length + 1),
94
+ columnType: (0, describe_query_1.verifyNotInferred)(param),
95
+ notNull: column.notNull
96
+ });
97
+ });
98
+ });
99
+ const typeInferenceResult = {
100
+ kind: 'Insert',
101
+ parameters: allParameters
102
+ };
103
+ return typeInferenceResult;
104
+ }
105
+ exports.analiseInsertStatement = analiseInsertStatement;
106
+ function analiseDeleteStatement(deleteStatement, dbSchema) {
107
+ var _a;
108
+ const whereExpr = (_a = deleteStatement.whereClause()) === null || _a === void 0 ? void 0 : _a.expr();
109
+ const deleteColumns = getDeleteColumns(deleteStatement, dbSchema);
110
+ const allParameters = [];
111
+ if (whereExpr) {
112
+ const context = {
113
+ fromColumns: deleteColumns,
114
+ parameters: [],
115
+ constraints: [],
116
+ dbSchema
117
+ };
118
+ walkExpr(context, whereExpr);
119
+ const typeInfo = generateTypeInfo(context.parameters, context.constraints);
120
+ const paramNullability = (0, infer_param_nullability_1.inferParamNullability)(whereExpr);
121
+ typeInfo.forEach((param, paramIndex) => {
122
+ allParameters.push({
123
+ name: 'param' + (allParameters.length + 1),
124
+ columnType: (0, describe_query_1.verifyNotInferred)(param),
125
+ notNull: paramNullability[paramIndex]
126
+ });
127
+ });
128
+ }
129
+ const typeInferenceResult = {
130
+ kind: 'Delete',
131
+ parameters: allParameters
132
+ };
133
+ return typeInferenceResult;
134
+ }
135
+ exports.analiseDeleteStatement = analiseDeleteStatement;
136
+ function analiseUpdateStatement(updateStatement, dbSchema) {
137
+ var _a;
138
+ const updateElement = updateStatement.updateList().updateElement();
139
+ const updateColumns = getUpdateColumns(updateStatement, dbSchema);
140
+ const dataParameters = [];
141
+ const whereParameters = [];
142
+ updateElement.forEach(updateElement => {
143
+ const expr = updateElement.expr();
144
+ if (expr) {
145
+ const context = {
146
+ dbSchema,
147
+ parameters: [],
148
+ constraints: [],
149
+ fromColumns: updateColumns
150
+ };
151
+ const result = walkExpr(context, expr);
152
+ const columnName = updateElement.columnRef().text;
153
+ const field = (0, select_columns_1.splitName)(columnName);
154
+ const column = (0, select_columns_1.findColumn)(field, updateColumns);
155
+ context.constraints.push({
156
+ expression: updateStatement.text,
157
+ type1: result,
158
+ type2: freshVar(column.table, column.columnType)
159
+ });
160
+ const typeInfo = generateTypeInfo(context.parameters, context.constraints);
161
+ typeInfo.forEach(param => {
162
+ dataParameters.push({
163
+ name: column.columnName,
164
+ columnType: (0, describe_query_1.verifyNotInferred)(param),
165
+ notNull: column.notNull
166
+ });
167
+ });
168
+ }
169
+ });
170
+ const whereExpr = (_a = updateStatement.whereClause()) === null || _a === void 0 ? void 0 : _a.expr();
171
+ if (whereExpr) {
172
+ const context = {
173
+ dbSchema,
174
+ parameters: [],
175
+ constraints: [],
176
+ fromColumns: updateColumns
177
+ };
178
+ walkExpr(context, whereExpr);
179
+ const typeInfo = generateTypeInfo(context.parameters, context.constraints);
180
+ const paramNullability = (0, infer_param_nullability_1.inferParamNullability)(whereExpr);
181
+ typeInfo.forEach((param, paramIndex) => {
182
+ whereParameters.push({
183
+ name: 'param' + (whereParameters.length + 1),
184
+ columnType: (0, describe_query_1.verifyNotInferred)(param),
185
+ notNull: paramNullability[paramIndex]
186
+ });
187
+ });
188
+ }
189
+ const typeInferenceResult = {
190
+ kind: 'Update',
191
+ data: dataParameters,
192
+ parameters: whereParameters
193
+ };
194
+ return typeInferenceResult;
195
+ }
196
+ exports.analiseUpdateStatement = analiseUpdateStatement;
197
+ function getInsertColumns(insertStatement, dbSchema) {
198
+ var _a, _b;
199
+ const insertIntoTable = (0, select_columns_1.splitName)(insertStatement.tableRef().text).name;
200
+ const fields = (_b = (_a = insertStatement.insertFromConstructor()) === null || _a === void 0 ? void 0 : _a.fields()) === null || _b === void 0 ? void 0 : _b.insertIdentifier().map(insertIdentifier => {
201
+ const colRef = insertIdentifier.columnRef();
202
+ if (colRef) {
203
+ const fieldName = (0, select_columns_1.splitName)(colRef.text);
204
+ const column = (0, select_columns_1.findColumn2)(fieldName, insertIntoTable, dbSchema);
205
+ return column;
206
+ }
207
+ throw Error('Invalid sql');
208
+ });
209
+ //check insert stmt without fields (only values). Ex.: insert into mytable values()
210
+ if (!fields) {
211
+ return dbSchema.filter(column => column.table == insertIntoTable);
212
+ }
213
+ return fields;
214
+ }
215
+ exports.getInsertColumns = getInsertColumns;
216
+ function getUpdateColumns(updateStatement, dbSchema) {
217
+ const insertIntoTable = (0, select_columns_1.splitName)(updateStatement.tableReferenceList().tableReference()[0].text).name;
218
+ const columns = dbSchema
219
+ .filter(col => col.table == insertIntoTable)
220
+ .map(col => {
221
+ const colDef = {
222
+ table: col.table,
223
+ column: col.column,
224
+ columnName: col.column,
225
+ columnType: col.column_type,
226
+ columnKey: col.columnKey,
227
+ notNull: col.notNull,
228
+ tableAlias: ''
229
+ };
230
+ return colDef;
231
+ });
232
+ return columns;
233
+ }
234
+ exports.getUpdateColumns = getUpdateColumns;
235
+ function getDeleteColumns(deleteStatement, dbSchema) {
236
+ var _a, _b;
237
+ const tableNameStr = (_a = deleteStatement.tableRef()) === null || _a === void 0 ? void 0 : _a.text;
238
+ const tableAlias = (_b = deleteStatement.tableAlias()) === null || _b === void 0 ? void 0 : _b.text;
239
+ const tableName = (0, select_columns_1.splitName)(tableNameStr).name;
240
+ const columns = dbSchema
241
+ .filter(col => col.table == tableName)
242
+ .map(col => {
243
+ const colDef = {
244
+ table: col.table,
245
+ column: col.column,
246
+ columnName: col.column,
247
+ columnType: col.column_type,
248
+ columnKey: col.columnKey,
249
+ notNull: col.notNull,
250
+ tableAlias: tableAlias
251
+ };
252
+ return colDef;
253
+ });
254
+ return columns;
255
+ }
256
+ exports.getDeleteColumns = getDeleteColumns;
257
+ function analiseSelectStatement(selectStatement, dbSchema, namedParameters) {
258
+ const querySpec = (0, parse_1.getQuerySpecificationsFromSelectStatement)(selectStatement);
259
+ const fromColumns = (0, select_columns_1.getColumnsFrom)(querySpec[0], dbSchema);
260
+ let result = analiseQuerySpecification(querySpec[0], dbSchema, namedParameters, fromColumns);
261
+ for (let index = 1; index < querySpec.length; index++) {
262
+ const unionQuery = querySpec[index];
263
+ const fromColumns2 = (0, select_columns_1.getColumnsFrom)(unionQuery, dbSchema);
264
+ const result2 = analiseQuerySpecification(unionQuery, dbSchema, namedParameters, fromColumns2);
265
+ result = unionResult(result, result2);
266
+ }
267
+ return result;
268
+ }
269
+ exports.analiseSelectStatement = analiseSelectStatement;
270
+ function unionResult(typeInference1, typeInference2) {
271
+ const resultColumnTypes = typeInference1.columns.map((col1, index) => {
272
+ const col2 = typeInference2.columns[index];
273
+ const resultType = unionTypeResult(col1, col2);
274
+ return resultType;
275
+ });
276
+ return {
277
+ columns: resultColumnTypes,
278
+ parameters: [...typeInference1.parameters, ...typeInference2.parameters] //TODO-INVERSE?
279
+ };
280
+ }
281
+ function unionTypeResult(type1, type2) {
282
+ const typeOrder = ['tinyint', 'smallint', 'mediumint', 'int', 'bigint', 'float', 'double', 'varchar'];
283
+ const indexType1 = typeOrder.indexOf(type1);
284
+ const indexType2 = typeOrder.indexOf(type2);
285
+ const max = Math.max(indexType1, indexType2);
286
+ return typeOrder[max];
287
+ }
288
+ exports.unionTypeResult = unionTypeResult;
289
+ function analiseQuerySpecification(querySpec, dbSchema, namedParameters, fromColumns) {
290
+ const context = {
291
+ dbSchema,
292
+ parameters: [],
293
+ constraints: [],
294
+ fromColumns: fromColumns
295
+ };
296
+ const queryTypes = walkQuerySpecification(context, querySpec);
297
+ const paramIndexes = (0, util_1.getParameterIndexes)(namedParameters); //for [a, a, b, a] will return a: [0, 1, 3]; b: [2]
298
+ paramIndexes.forEach(paramIndex => {
299
+ (0, util_1.getPairWise)(paramIndex.indexes, (cur, next) => {
300
+ context.constraints.push({
301
+ expression: paramIndex.paramName,
302
+ type1: context.parameters[cur],
303
+ type2: context.parameters[next]
304
+ });
305
+ });
306
+ });
307
+ // console.log("namedNodes");
308
+ // console.dir(namedNodes, { depth: null });
309
+ // console.log("constraints2=");
310
+ // console.dir(constraints, { depth: null });
311
+ const substitutions = {};
312
+ (0, unify_1.unify)(context.constraints, substitutions);
313
+ const parameters = context.parameters.map(param => getVarType(substitutions, param));
314
+ const columnTypes = queryTypes.types.map(param => getVarType(substitutions, param));
315
+ const querySpecResult = {
316
+ parameters: parameters,
317
+ columns: columnTypes
318
+ };
319
+ return querySpecResult;
320
+ }
321
+ exports.analiseQuerySpecification = analiseQuerySpecification;
322
+ function generateTypeInfo(namedNodes, constraints) {
323
+ const substitutions = {};
324
+ (0, unify_1.unify)(constraints, substitutions);
325
+ const parameters = namedNodes.map(param => getVarType(substitutions, param));
326
+ return parameters;
327
+ }
328
+ exports.generateTypeInfo = generateTypeInfo;
329
+ function getVarType(substitutions, typeVar) {
330
+ if (typeVar.kind == 'TypeVar') {
331
+ const type = substitutions[typeVar.id];
332
+ if (!type) {
333
+ return typeVar.type;
334
+ }
335
+ const resultType = typeVar.list ? type.type + '[]' : type.type;
336
+ return resultType;
337
+ }
338
+ return '?';
339
+ }
340
+ function walkQuerySpecification(context, querySpec) {
341
+ const listType = [];
342
+ if (querySpec.selectItemList().MULT_OPERATOR()) {
343
+ context.fromColumns.forEach(col => {
344
+ const colType = freshVar(col.columnName, col.columnType);
345
+ listType.push(colType);
346
+ });
347
+ }
348
+ querySpec.selectItemList().selectItem().forEach(selectItem => {
349
+ const tableWild = selectItem.tableWild(); //ex. t1.*
350
+ if (tableWild === null || tableWild === void 0 ? void 0 : tableWild.MULT_OPERATOR()) {
351
+ tableWild.identifier().forEach(tabWild => {
352
+ const prefix = tabWild.text;
353
+ const columns = (0, select_columns_1.selectAllColumns)(prefix, context.fromColumns);
354
+ columns.forEach(col => {
355
+ const colType = freshVar(col.columnName, col.columnType);
356
+ listType.push(colType);
357
+ });
358
+ });
359
+ }
360
+ else {
361
+ const expr = selectItem.expr();
362
+ if (expr) {
363
+ const exprType = walkExpr(context, expr);
364
+ if (exprType.kind == 'TypeOperator') {
365
+ const subqueryType = exprType.types[0];
366
+ listType.push(subqueryType);
367
+ }
368
+ else {
369
+ listType.push(exprType);
370
+ }
371
+ }
372
+ }
373
+ });
374
+ const typeOperator = {
375
+ kind: 'TypeOperator',
376
+ selectItem: true,
377
+ types: listType
378
+ };
379
+ const fromClause = querySpec.fromClause();
380
+ if (fromClause) {
381
+ walkFromClause(context, fromClause);
382
+ }
383
+ const whereClause = querySpec.whereClause();
384
+ //TODO - HAVING, BLAH
385
+ if (whereClause) {
386
+ const whereExpr = whereClause === null || whereClause === void 0 ? void 0 : whereClause.expr();
387
+ walkExpr(context, whereExpr);
388
+ }
389
+ return typeOperator;
390
+ }
391
+ exports.walkQuerySpecification = walkQuerySpecification;
392
+ function walkFromClause(context, fromClause) {
393
+ var _a;
394
+ const tableReferences = (_a = fromClause.tableReferenceList()) === null || _a === void 0 ? void 0 : _a.tableReference();
395
+ tableReferences === null || tableReferences === void 0 ? void 0 : tableReferences.forEach(tabeRef => {
396
+ tabeRef.joinedTable().forEach(joinedTable => {
397
+ const onExpr = joinedTable.expr();
398
+ if (onExpr) {
399
+ walkExpr(context, onExpr);
400
+ }
401
+ });
402
+ });
403
+ }
404
+ function walkExpr(context, expr) {
405
+ if (expr instanceof ts_mysql_parser_1.ExprIsContext) {
406
+ const boolPri = expr.boolPri();
407
+ const boolPriType = walkBoolPri(context, boolPri);
408
+ return boolPriType;
409
+ }
410
+ if (expr instanceof ts_mysql_parser_1.ExprNotContext) {
411
+ return freshVar(expr.text, 'tinyint');
412
+ ;
413
+ }
414
+ if (expr instanceof ts_mysql_parser_1.ExprAndContext || expr instanceof ts_mysql_parser_1.ExprXorContext || expr instanceof ts_mysql_parser_1.ExprOrContext) {
415
+ const exprLeft = expr.expr()[0];
416
+ walkExpr(context, exprLeft);
417
+ const exprRight = expr.expr()[1];
418
+ walkExpr(context, exprRight);
419
+ return freshVar(expr.text, 'tinyint');
420
+ }
421
+ throw Error('invalid type');
422
+ }
423
+ function walkBoolPri(context, boolPri) {
424
+ if (boolPri instanceof ts_mysql_parser_1.PrimaryExprPredicateContext) {
425
+ const predicate = boolPri.predicate();
426
+ const predicateType = walkPredicate(context, predicate);
427
+ return predicateType;
428
+ }
429
+ if (boolPri instanceof ts_mysql_parser_1.PrimaryExprIsNullContext) {
430
+ const boolPri2 = boolPri.boolPri();
431
+ walkBoolPri(context, boolPri2);
432
+ return freshVar(boolPri.text, '?');
433
+ }
434
+ if (boolPri instanceof ts_mysql_parser_1.PrimaryExprCompareContext) {
435
+ const compareLeft = boolPri.boolPri();
436
+ const compareRight = boolPri.predicate();
437
+ const typeLeft = walkBoolPri(context, compareLeft);
438
+ const typeRight = walkPredicate(context, compareRight);
439
+ context.constraints.push({
440
+ expression: boolPri.text,
441
+ type1: typeLeft,
442
+ type2: typeRight
443
+ });
444
+ return freshVar(boolPri.text, 'tinyint');
445
+ }
446
+ if (boolPri instanceof ts_mysql_parser_1.PrimaryExprAllAnyContext) {
447
+ const compareLeft = boolPri.boolPri();
448
+ const compareRight = boolPri.subquery();
449
+ const typeLeft = walkBoolPri(context, compareLeft);
450
+ const typeRight = walkSubquery(context, compareRight);
451
+ context.constraints.push({
452
+ expression: boolPri.text,
453
+ type1: typeLeft,
454
+ type2: typeRight
455
+ });
456
+ return freshVar(boolPri.text, 'tinyint');
457
+ }
458
+ throw Error('invalid sql');
459
+ }
460
+ function walkPredicate(context, predicate) {
461
+ const bitExpr = predicate.bitExpr()[0];
462
+ const bitExprType = walkBitExpr(context, bitExpr);
463
+ const predicateOperations = predicate.predicateOperations();
464
+ if (predicateOperations) {
465
+ const rightType = walkpredicateOperations(context, bitExprType, predicateOperations);
466
+ context.constraints.push({
467
+ expression: predicateOperations.text,
468
+ type1: bitExprType,
469
+ type2: rightType,
470
+ mostGeneralType: true
471
+ });
472
+ return rightType;
473
+ }
474
+ // return freshVar(predicateOperations.text, 'tinyint');
475
+ return bitExprType;
476
+ }
477
+ function walkpredicateOperations(context, parentType, predicateOperations) {
478
+ if (predicateOperations instanceof ts_mysql_parser_1.PredicateExprInContext) {
479
+ const subquery = predicateOperations.subquery();
480
+ if (subquery) {
481
+ const rightType = walkSubquery(context, subquery);
482
+ return rightType;
483
+ }
484
+ const exprList = predicateOperations.exprList();
485
+ if (exprList) {
486
+ const rightType = walkExprList(context, exprList);
487
+ return rightType;
488
+ }
489
+ }
490
+ if (predicateOperations instanceof ts_mysql_parser_1.PredicateExprLikeContext) {
491
+ const simpleExpr = predicateOperations.simpleExpr()[0];
492
+ const rightType = walkSimpleExpr(context, simpleExpr);
493
+ context.constraints.push({
494
+ expression: simpleExpr.text,
495
+ type1: parentType,
496
+ type2: rightType
497
+ });
498
+ return rightType;
499
+ }
500
+ throw Error("Not expected");
501
+ }
502
+ function walkExprList(context, exprList) {
503
+ const listType = exprList.expr().map(item => {
504
+ const exprType = walkExpr(context, item);
505
+ return exprType;
506
+ });
507
+ const type = {
508
+ kind: 'TypeOperator',
509
+ types: listType
510
+ };
511
+ return type;
512
+ }
513
+ function walkBitExpr(context, bitExpr) {
514
+ const simpleExpr = bitExpr.simpleExpr();
515
+ if (simpleExpr) {
516
+ return walkSimpleExpr(context, simpleExpr);
517
+ }
518
+ if (bitExpr.bitExpr().length == 2) {
519
+ const bitExprType = freshVar(bitExpr.text, 'number');
520
+ const bitExprLeft = bitExpr.bitExpr()[0];
521
+ const typeLeftTemp = walkBitExpr(context, bitExprLeft);
522
+ const typeLeft = typeLeftTemp.kind == 'TypeOperator' ? typeLeftTemp.types[0] : typeLeftTemp;
523
+ //const newTypeLeft = typeLeft.name == '?'? freshVar('?', 'bigint') : typeLeft;
524
+ const bitExprRight = bitExpr.bitExpr()[1];
525
+ const typeRightTemp = walkBitExpr(context, bitExprRight);
526
+ //In the expression 'id + (value + 2) + ?' the '(value+2)' is treated as a SimpleExprListContext and return a TypeOperator
527
+ const typeRight = typeRightTemp.kind == 'TypeOperator' ? typeRightTemp.types[0] : typeRightTemp;
528
+ //const newTypeRight = typeRight.name == '?'? freshVar('?', 'bigint') : typeRight;
529
+ context.constraints.push({
530
+ expression: bitExpr.text,
531
+ type1: typeLeft,
532
+ type2: typeRight,
533
+ mostGeneralType: true,
534
+ coercionType: 'Sum'
535
+ });
536
+ context.constraints.push({
537
+ expression: bitExpr.text,
538
+ type1: bitExprType,
539
+ type2: typeLeft,
540
+ mostGeneralType: true,
541
+ coercionType: 'Sum'
542
+ });
543
+ context.constraints.push({
544
+ expression: bitExpr.text,
545
+ type1: bitExprType,
546
+ type2: typeRight,
547
+ mostGeneralType: true,
548
+ coercionType: 'Sum'
549
+ });
550
+ return bitExprType;
551
+ }
552
+ if (bitExpr.INTERVAL_SYMBOL()) {
553
+ const bitExpr2 = bitExpr.bitExpr()[0];
554
+ const leftType = walkBitExpr(context, bitExpr2);
555
+ const expr = bitExpr.expr(); //expr interval
556
+ walkExpr(context, expr);
557
+ context.constraints.push({
558
+ expression: bitExpr.text,
559
+ type1: leftType,
560
+ type2: freshVar('datetime', 'datetime')
561
+ });
562
+ return freshVar('datetime', 'datetime');
563
+ }
564
+ throw Error('Invalid sql');
565
+ }
566
+ function walkSimpleExpr(context, simpleExpr) {
567
+ var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p;
568
+ if (simpleExpr instanceof ts_mysql_parser_1.SimpleExprColumnRefContext) {
569
+ const fieldName = (0, select_columns_1.splitName)(simpleExpr.text);
570
+ const columnType = (0, select_columns_1.findColumn)(fieldName, context.fromColumns).columnType;
571
+ const type = freshVar(simpleExpr.text, columnType);
572
+ return type;
573
+ }
574
+ if (simpleExpr instanceof ts_mysql_parser_1.SimpleExprRuntimeFunctionContext) {
575
+ const runtimeFunctionCall = simpleExpr.runtimeFunctionCall();
576
+ if (runtimeFunctionCall.NOW_SYMBOL()) {
577
+ return freshVar(simpleExpr.text, 'datetime');
578
+ }
579
+ if (runtimeFunctionCall.CURDATE_SYMBOL()) {
580
+ return freshVar(simpleExpr.text, 'date');
581
+ }
582
+ if (runtimeFunctionCall.CURTIME_SYMBOL()) {
583
+ return freshVar(simpleExpr.text, 'time');
584
+ }
585
+ if (runtimeFunctionCall.REPLACE_SYMBOL()) {
586
+ const exprList = runtimeFunctionCall.expr();
587
+ exprList.forEach(expr => {
588
+ const exprType = walkExpr(context, expr);
589
+ context.constraints.push({
590
+ expression: expr.text,
591
+ type1: exprType,
592
+ type2: freshVar('varchar', 'varchar')
593
+ });
594
+ });
595
+ return freshVar('varchar', 'varchar');
596
+ }
597
+ if (runtimeFunctionCall.YEAR_SYMBOL() || runtimeFunctionCall.MONTH_SYMBOL() || runtimeFunctionCall.DAY_SYMBOL()) {
598
+ const expr = (_a = runtimeFunctionCall.exprWithParentheses()) === null || _a === void 0 ? void 0 : _a.expr();
599
+ if (expr) {
600
+ const paramType = walkExpr(context, expr);
601
+ if (paramType.kind == 'TypeVar' && isDateTimeLiteral(paramType.name)) {
602
+ paramType.type = 'datetime';
603
+ }
604
+ if (paramType.kind == 'TypeVar' && isDateLiteral(paramType.name)) {
605
+ paramType.type = 'date';
606
+ }
607
+ context.constraints.push({
608
+ expression: expr.text,
609
+ type1: paramType,
610
+ type2: freshVar(simpleExpr.text, 'date')
611
+ });
612
+ }
613
+ const returnType = runtimeFunctionCall.YEAR_SYMBOL() ? 'year' : 'tinyint';
614
+ return freshVar(simpleExpr.text, returnType);
615
+ }
616
+ if (runtimeFunctionCall.HOUR_SYMBOL() || runtimeFunctionCall.MINUTE_SYMBOL() || runtimeFunctionCall.SECOND_SYMBOL()) {
617
+ const expr = (_b = runtimeFunctionCall.exprWithParentheses()) === null || _b === void 0 ? void 0 : _b.expr();
618
+ if (expr) {
619
+ const paramType = walkExpr(context, expr);
620
+ if (paramType.kind == 'TypeVar' && isTimeLiteral(paramType.name)) {
621
+ paramType.type = 'time';
622
+ }
623
+ if (paramType.kind == 'TypeVar' && isDateLiteral(paramType.name)) {
624
+ paramType.type = 'date';
625
+ }
626
+ if (paramType.kind == 'TypeVar' && isDateTimeLiteral(paramType.name)) {
627
+ paramType.type = 'datetime';
628
+ }
629
+ context.constraints.push({
630
+ expression: expr.text,
631
+ type1: paramType,
632
+ type2: freshVar(simpleExpr.text, 'time')
633
+ });
634
+ }
635
+ //HOUR can return values greater than 23. Ex.: SELECT HOUR('272:59:59');
636
+ //https://dev.mysql.com/doc/refman/8.0/en/date-and-time-functions.html#function_hour
637
+ const returnType = runtimeFunctionCall.HOUR_SYMBOL() ? 'int' : 'tinyint';
638
+ return freshVar(simpleExpr.text, returnType);
639
+ }
640
+ const trimFunction = runtimeFunctionCall.trimFunction();
641
+ if (trimFunction) {
642
+ const exprList = trimFunction.expr();
643
+ if (exprList.length == 1) {
644
+ const exprType = walkExpr(context, exprList[0]);
645
+ context.constraints.push({
646
+ expression: exprList[0].text,
647
+ type1: exprType,
648
+ type2: freshVar('varchar', 'varchar')
649
+ });
650
+ }
651
+ if (exprList.length == 2) {
652
+ const exprType = walkExpr(context, exprList[0]);
653
+ const expr2Type = walkExpr(context, exprList[1]);
654
+ context.constraints.push({
655
+ expression: exprList[0].text,
656
+ type1: exprType,
657
+ type2: freshVar('varchar', 'varchar')
658
+ });
659
+ context.constraints.push({
660
+ expression: exprList[1].text,
661
+ type1: expr2Type,
662
+ type2: freshVar('varchar', 'varchar')
663
+ });
664
+ }
665
+ return freshVar('varchar', 'varchar');
666
+ }
667
+ const substringFunction = runtimeFunctionCall.substringFunction();
668
+ if (substringFunction) {
669
+ const exprList = substringFunction.expr();
670
+ const varcharParam = freshVar('varchar', 'varchar');
671
+ const intParam = freshVar('int', 'int');
672
+ const params = {
673
+ kind: 'FixedLengthParams',
674
+ paramsType: [varcharParam, intParam, intParam]
675
+ };
676
+ walkExprListParameters(context, exprList, params);
677
+ return varcharParam;
678
+ }
679
+ if (runtimeFunctionCall.ADDDATE_SYMBOL()
680
+ || runtimeFunctionCall.DATE_ADD_SYMBOL()
681
+ || runtimeFunctionCall.SUBDATE_SYMBOL()
682
+ || runtimeFunctionCall.DATE_SUB_SYMBOL()) {
683
+ //SELECT ADDDATE('2008-01-02', INTERVAL 31 DAY)
684
+ //SELECT ADDDATE('2008-01-02', 31)
685
+ const expr1 = runtimeFunctionCall.expr()[0];
686
+ const expr2 = runtimeFunctionCall.expr()[1];
687
+ const typeExpr1 = walkExpr(context, expr1);
688
+ const typeExpr2 = walkExpr(context, expr2);
689
+ if (typeExpr1.kind == 'TypeVar' && (isDateLiteral(typeExpr1.name) || isDateTimeLiteral(typeExpr1.name))) {
690
+ typeExpr1.type = 'datetime';
691
+ }
692
+ context.constraints.push({
693
+ expression: expr1.text,
694
+ type1: typeExpr1,
695
+ type2: freshVar('datetime', 'datetime')
696
+ });
697
+ context.constraints.push({
698
+ expression: expr2.text,
699
+ type1: typeExpr2,
700
+ type2: freshVar('bigint', 'bigint')
701
+ });
702
+ return freshVar('datetime', 'datetime');
703
+ }
704
+ if (runtimeFunctionCall.COALESCE_SYMBOL()) {
705
+ const exprList = (_c = runtimeFunctionCall.exprListWithParentheses()) === null || _c === void 0 ? void 0 : _c.exprList().expr();
706
+ if (exprList) {
707
+ const paramType = freshVar('?', '?');
708
+ const params = {
709
+ kind: 'VariableLengthParams',
710
+ paramType: 'any'
711
+ };
712
+ const paramsTypeList = walkExprListParameters(context, exprList, params);
713
+ paramsTypeList.forEach((typeVar, paramIndex) => {
714
+ context.constraints.push({
715
+ expression: runtimeFunctionCall.text + '_param' + (paramIndex + 1),
716
+ type1: paramType,
717
+ type2: typeVar,
718
+ mostGeneralType: true,
719
+ coercionType: 'Coalesce'
720
+ });
721
+ });
722
+ return paramType;
723
+ }
724
+ }
725
+ //MOD (number, number): number
726
+ if (runtimeFunctionCall.MOD_SYMBOL()) {
727
+ const functionType = freshVar('number', 'number');
728
+ const exprList = runtimeFunctionCall.expr();
729
+ const param1 = walkExpr(context, exprList[0]);
730
+ const param2 = walkExpr(context, exprList[1]);
731
+ context.constraints.push({
732
+ expression: simpleExpr.text,
733
+ type1: freshVar('number', 'number'),
734
+ type2: param1,
735
+ mostGeneralType: true
736
+ });
737
+ context.constraints.push({
738
+ expression: simpleExpr.text,
739
+ type1: freshVar('number', 'number'),
740
+ type2: param2,
741
+ mostGeneralType: true
742
+ });
743
+ context.constraints.push({
744
+ expression: simpleExpr.text,
745
+ type1: functionType,
746
+ type2: param1,
747
+ mostGeneralType: true
748
+ });
749
+ context.constraints.push({
750
+ expression: simpleExpr.text,
751
+ type1: functionType,
752
+ type2: param2,
753
+ mostGeneralType: true
754
+ });
755
+ return functionType;
756
+ }
757
+ throw Error('Function not supported: ' + runtimeFunctionCall.text);
758
+ }
759
+ if (simpleExpr instanceof ts_mysql_parser_1.SimpleExprFunctionContext) {
760
+ const functionIdentifier = getFunctionName(simpleExpr);
761
+ if (functionIdentifier === 'concat_ws' || (functionIdentifier === null || functionIdentifier === void 0 ? void 0 : functionIdentifier.toLowerCase()) === 'concat') {
762
+ const varcharType = freshVar(simpleExpr.text, 'varchar');
763
+ const params = {
764
+ kind: 'VariableLengthParams',
765
+ paramType: '?'
766
+ };
767
+ walkFunctionParameters(context, simpleExpr, params);
768
+ return varcharType;
769
+ }
770
+ if (functionIdentifier === 'avg') {
771
+ const functionType = freshVar(simpleExpr.text, '?');
772
+ context.constraints.push({
773
+ expression: simpleExpr.text,
774
+ type1: functionType,
775
+ type2: freshVar('decimal', 'decimal'),
776
+ mostGeneralType: true
777
+ });
778
+ const params = {
779
+ kind: 'FixedLengthParams',
780
+ paramsType: [functionType]
781
+ };
782
+ walkFunctionParameters(context, simpleExpr, params);
783
+ return functionType;
784
+ }
785
+ if (functionIdentifier === 'round') {
786
+ const functionType = freshVar(simpleExpr.text, '?');
787
+ const params = {
788
+ kind: 'FixedLengthParams',
789
+ paramsType: [functionType]
790
+ };
791
+ const paramsType = walkFunctionParameters(context, simpleExpr, params);
792
+ //The return value has the same type as the first argument
793
+ context.constraints.push({
794
+ expression: simpleExpr.text,
795
+ type1: functionType,
796
+ type2: paramsType[0],
797
+ mostGeneralType: true
798
+ });
799
+ return functionType;
800
+ }
801
+ if (functionIdentifier === 'floor') {
802
+ const doubleParam = freshVar('double', 'double');
803
+ const params = {
804
+ kind: 'FixedLengthParams',
805
+ paramsType: [doubleParam, doubleParam]
806
+ };
807
+ walkFunctionParameters(context, simpleExpr, params);
808
+ return freshVar(simpleExpr.text, 'bigint');
809
+ }
810
+ if (functionIdentifier === 'str_to_date') {
811
+ const varcharParam = freshVar('varchar', 'varchar');
812
+ const params = {
813
+ kind: 'FixedLengthParams',
814
+ paramsType: [varcharParam, varcharParam]
815
+ };
816
+ walkFunctionParameters(context, simpleExpr, params);
817
+ return freshVar(simpleExpr.text, 'date');
818
+ }
819
+ if (functionIdentifier === 'datediff') {
820
+ const udfExprList = (_d = simpleExpr.functionCall().udfExprList()) === null || _d === void 0 ? void 0 : _d.udfExpr();
821
+ if (udfExprList) {
822
+ udfExprList.forEach((inExpr) => {
823
+ const expr = inExpr.expr();
824
+ const exprType = walkExpr(context, expr);
825
+ const newType = verifyDateTypesCoercion(exprType);
826
+ context.constraints.push({
827
+ expression: expr.text,
828
+ type1: newType,
829
+ type2: freshVar('date', 'date'),
830
+ mostGeneralType: true
831
+ });
832
+ });
833
+ }
834
+ return freshVar(simpleExpr.text, 'bigint');
835
+ }
836
+ if (functionIdentifier === 'lpad' || functionIdentifier == 'rpad') {
837
+ const varcharParam = freshVar('varchar', 'varchar');
838
+ const intParam = freshVar('int', 'int');
839
+ const params = {
840
+ kind: 'FixedLengthParams',
841
+ paramsType: [varcharParam, intParam, varcharParam]
842
+ };
843
+ walkFunctionParameters(context, simpleExpr, params);
844
+ return varcharParam;
845
+ }
846
+ if (functionIdentifier === 'lower'
847
+ || functionIdentifier === 'lcase'
848
+ || functionIdentifier === 'upper'
849
+ || functionIdentifier === 'ucase'
850
+ || functionIdentifier === 'ltrim'
851
+ || functionIdentifier === 'rtrim') {
852
+ const varcharParam = freshVar('varchar', 'varchar');
853
+ const params = {
854
+ kind: 'FixedLengthParams',
855
+ paramsType: [varcharParam]
856
+ };
857
+ walkFunctionParameters(context, simpleExpr, params);
858
+ return varcharParam;
859
+ }
860
+ if (functionIdentifier === 'length' || functionIdentifier == 'char_length') {
861
+ const varcharParam = freshVar('varchar', 'varchar');
862
+ const params = {
863
+ kind: 'FixedLengthParams',
864
+ paramsType: [varcharParam]
865
+ };
866
+ walkFunctionParameters(context, simpleExpr, params);
867
+ return freshVar('int', 'int');
868
+ }
869
+ if (functionIdentifier === 'abs') {
870
+ const functionType = freshVar('number', 'number');
871
+ const udfExprList = (_e = simpleExpr.functionCall().udfExprList()) === null || _e === void 0 ? void 0 : _e.udfExpr();
872
+ udfExprList === null || udfExprList === void 0 ? void 0 : udfExprList.forEach(expr => {
873
+ const param1 = walkExpr(context, expr.expr());
874
+ context.constraints.push({
875
+ expression: simpleExpr.text,
876
+ type1: functionType,
877
+ type2: param1,
878
+ mostGeneralType: true
879
+ });
880
+ });
881
+ return functionType;
882
+ }
883
+ if (functionIdentifier == 'ceiling' || functionIdentifier == 'ceil') {
884
+ const functionType = freshVar('number', 'number');
885
+ const udfExprList = (_f = simpleExpr.functionCall().udfExprList()) === null || _f === void 0 ? void 0 : _f.udfExpr();
886
+ udfExprList === null || udfExprList === void 0 ? void 0 : udfExprList.forEach(expr => {
887
+ const param1 = walkExpr(context, expr.expr());
888
+ context.constraints.push({
889
+ expression: simpleExpr.text,
890
+ type1: functionType,
891
+ type2: param1,
892
+ mostGeneralType: true,
893
+ coercionType: 'Ceiling'
894
+ });
895
+ });
896
+ return functionType;
897
+ }
898
+ if (functionIdentifier == 'timestampdiff') {
899
+ const udfExprList = (_g = simpleExpr.functionCall().udfExprList()) === null || _g === void 0 ? void 0 : _g.udfExpr();
900
+ if (udfExprList) {
901
+ const [first, ...rest] = udfExprList;
902
+ const unit = first.text.trim().toLowerCase();
903
+ rest.forEach((inExpr, paramIndex) => {
904
+ const expr = inExpr.expr();
905
+ const exprType = walkExpr(context, expr);
906
+ const newType = verifyDateTypesCoercion(exprType);
907
+ //const expectedType = ['hour', 'minute', 'second'].includes(unit)? 'time' : 'datetime'
908
+ context.constraints.push({
909
+ expression: expr.text,
910
+ type1: newType,
911
+ type2: freshVar('datetime', 'datetime'),
912
+ mostGeneralType: true
913
+ });
914
+ });
915
+ }
916
+ return freshVar('int', 'int');
917
+ }
918
+ if (functionIdentifier == 'ifnull') {
919
+ const functionType = freshVar(simpleExpr.text, '?');
920
+ const udfExprList = (_h = simpleExpr.functionCall().udfExprList()) === null || _h === void 0 ? void 0 : _h.udfExpr();
921
+ if (udfExprList) {
922
+ const [expr1, expr2] = udfExprList;
923
+ walkExpr(context, expr1.expr());
924
+ const expr2Type = walkExpr(context, expr2.expr());
925
+ context.constraints.push({
926
+ expression: simpleExpr.text,
927
+ type1: functionType,
928
+ type2: expr2Type
929
+ });
930
+ }
931
+ return functionType;
932
+ }
933
+ throw Error('Function not supported: ' + functionIdentifier); //TODO ifnull
934
+ }
935
+ if (simpleExpr instanceof ts_mysql_parser_1.SimpleExprParamMarkerContext) {
936
+ const param = freshVar('?', '?');
937
+ context.parameters.push(param);
938
+ return param;
939
+ }
940
+ if (simpleExpr instanceof ts_mysql_parser_1.SimpleExprSumContext) {
941
+ if (simpleExpr.sumExpr().MAX_SYMBOL() || simpleExpr.sumExpr().MIN_SYMBOL()) {
942
+ const functionType = freshVar(simpleExpr.text, '?');
943
+ const inSumExpr = (_j = simpleExpr.sumExpr().inSumExpr()) === null || _j === void 0 ? void 0 : _j.expr();
944
+ if (inSumExpr) {
945
+ const inSumExprType = walkExpr(context, inSumExpr);
946
+ context.constraints.push({
947
+ expression: simpleExpr.text,
948
+ type1: functionType,
949
+ type2: inSumExprType,
950
+ mostGeneralType: true
951
+ });
952
+ }
953
+ return functionType;
954
+ }
955
+ if (simpleExpr.sumExpr().COUNT_SYMBOL()) {
956
+ const functionType = freshVar(simpleExpr.text, 'bigint');
957
+ const inSumExpr = (_k = simpleExpr.sumExpr().inSumExpr()) === null || _k === void 0 ? void 0 : _k.expr();
958
+ if (inSumExpr) {
959
+ walkExpr(context, inSumExpr);
960
+ }
961
+ return functionType;
962
+ }
963
+ if (simpleExpr.sumExpr().SUM_SYMBOL() || simpleExpr.sumExpr().AVG_SYMBOL()) {
964
+ const functionType = freshVar(simpleExpr.text, '?');
965
+ const inSumExpr = (_l = simpleExpr.sumExpr().inSumExpr()) === null || _l === void 0 ? void 0 : _l.expr();
966
+ if (inSumExpr) {
967
+ const inSumExprType = walkExpr(context, inSumExpr);
968
+ context.constraints.push({
969
+ expression: simpleExpr.text,
970
+ type1: functionType,
971
+ type2: inSumExprType,
972
+ mostGeneralType: true,
973
+ coercionType: 'SumFunction'
974
+ });
975
+ }
976
+ return functionType;
977
+ }
978
+ }
979
+ if (simpleExpr instanceof ts_mysql_parser_1.SimpleExprLiteralContext) {
980
+ const literal = simpleExpr.literal();
981
+ if (literal.textLiteral()) {
982
+ const text = ((_m = literal.textLiteral()) === null || _m === void 0 ? void 0 : _m.text.slice(1, -1)) || ''; //remove quotes
983
+ return freshVar(text, 'varchar');
984
+ }
985
+ const numLiteral = literal.numLiteral();
986
+ if (numLiteral) {
987
+ return freshVar(numLiteral.text, 'bigint');
988
+ // addNamedNode(simpleExpr, freshVar('bigint', 'bigint'), namedNodes)
989
+ // if(numLiteral.INT_NUMBER()) {
990
+ // const typeInt = freshVar('int', 'int');
991
+ // addNamedNode(simpleExpr, typeInt, namedNodes)
992
+ // }
993
+ // if(numLiteral.DECIMAL_NUMBER()) {
994
+ // const typeDecimal = freshVar('decimal', 'decimal');
995
+ // addNamedNode(simpleExpr, typeDecimal, namedNodes)
996
+ // }
997
+ // if(numLiteral.FLOAT_NUMBER()) {
998
+ // const typeFloat = freshVar('float', 'float');
999
+ // addNamedNode(simpleExpr, typeFloat, namedNodes)
1000
+ // }
1001
+ ;
1002
+ }
1003
+ const boolLiteral = literal.boolLiteral();
1004
+ if (boolLiteral) {
1005
+ return freshVar(boolLiteral.text, 'bit');
1006
+ }
1007
+ const nullLiteral = literal.nullLiteral();
1008
+ if (nullLiteral) {
1009
+ return freshVar(nullLiteral.text, '?');
1010
+ }
1011
+ throw Error('literal not supported:' + literal.text);
1012
+ //...
1013
+ }
1014
+ if (simpleExpr instanceof ts_mysql_parser_1.SimpleExprListContext) {
1015
+ const exprList = simpleExpr.exprList();
1016
+ const listType = exprList.expr().map(item => {
1017
+ const exprType = walkExpr(context, item);
1018
+ return exprType;
1019
+ });
1020
+ const resultType = {
1021
+ kind: 'TypeOperator',
1022
+ types: listType
1023
+ };
1024
+ return resultType;
1025
+ }
1026
+ if (simpleExpr instanceof ts_mysql_parser_1.SimpleExprSubQueryContext) {
1027
+ const subquery = simpleExpr.subquery();
1028
+ const subqueryType = walkSubquery(context, subquery);
1029
+ return subqueryType;
1030
+ }
1031
+ if (simpleExpr instanceof ts_mysql_parser_1.SimpleExprCaseContext) {
1032
+ //case when expr then expr else expr
1033
+ const caseType = freshVar(simpleExpr.text, '?');
1034
+ simpleExpr.whenExpression().forEach(whenExprCont => {
1035
+ const whenExpr = whenExprCont.expr();
1036
+ const whenType = walkExpr(context, whenExpr);
1037
+ context.constraints.push({
1038
+ expression: whenExpr.text,
1039
+ type1: whenType.kind == 'TypeOperator' ? whenType.types[0] : whenType,
1040
+ type2: freshVar('tinyint', 'tinyint') //bool
1041
+ });
1042
+ });
1043
+ const thenTypes = simpleExpr.thenExpression().map(thenExprCtx => {
1044
+ const thenExpr = thenExprCtx.expr();
1045
+ const thenType = walkExpr(context, thenExpr);
1046
+ context.constraints.push({
1047
+ expression: thenExprCtx.text,
1048
+ type1: caseType,
1049
+ type2: thenType.kind == 'TypeOperator' ? thenType.types[0] : thenType,
1050
+ mostGeneralType: true,
1051
+ });
1052
+ return thenType;
1053
+ });
1054
+ const elseExpr = (_o = simpleExpr.elseExpression()) === null || _o === void 0 ? void 0 : _o.expr();
1055
+ if (elseExpr) {
1056
+ const elseType = walkExpr(context, elseExpr);
1057
+ context.constraints.push({
1058
+ expression: (_p = simpleExpr.elseExpression()) === null || _p === void 0 ? void 0 : _p.text,
1059
+ type1: caseType,
1060
+ type2: elseType.kind == 'TypeOperator' ? elseType.types[0] : elseType,
1061
+ mostGeneralType: true
1062
+ });
1063
+ thenTypes.forEach(thenType => {
1064
+ var _a;
1065
+ context.constraints.push({
1066
+ expression: (_a = simpleExpr.elseExpression()) === null || _a === void 0 ? void 0 : _a.text,
1067
+ type1: thenType,
1068
+ type2: elseType.kind == 'TypeOperator' ? elseType.types[0] : elseType,
1069
+ mostGeneralType: true
1070
+ });
1071
+ });
1072
+ }
1073
+ return caseType;
1074
+ }
1075
+ if (simpleExpr instanceof ts_mysql_parser_1.SimpleExprIntervalContext) {
1076
+ const exprList = simpleExpr.expr();
1077
+ const exprLeft = exprList[0];
1078
+ const exprRight = exprList[1];
1079
+ const typeLeft = walkExpr(context, exprLeft);
1080
+ const typeRight = walkExpr(context, exprRight);
1081
+ context.constraints.push({
1082
+ expression: exprLeft.text,
1083
+ type1: typeLeft,
1084
+ type2: freshVar('bigint', 'bigint')
1085
+ });
1086
+ if (typeRight.kind == 'TypeVar' && (isDateLiteral(typeRight.name) || isDateTimeLiteral(typeRight.name))) {
1087
+ typeRight.type = 'datetime';
1088
+ }
1089
+ context.constraints.push({
1090
+ expression: exprRight.text,
1091
+ type1: typeRight,
1092
+ type2: freshVar('datetime', 'datetime')
1093
+ });
1094
+ return freshVar('datetime', 'datetime');
1095
+ }
1096
+ throw Error('Invalid expression');
1097
+ }
1098
+ function verifyDateTypesCoercion(type) {
1099
+ if (type.kind == 'TypeVar' && isDateTimeLiteral(type.name)) {
1100
+ type.type = 'datetime';
1101
+ }
1102
+ if (type.kind == 'TypeVar' && isDateLiteral(type.name)) {
1103
+ type.type = 'date';
1104
+ }
1105
+ if (type.kind == 'TypeVar' && isTimeLiteral(type.name)) {
1106
+ type.type = 'time';
1107
+ }
1108
+ return type;
1109
+ }
1110
+ function isTimeLiteral(literal) {
1111
+ return (0, moment_1.default)(literal, 'HH:mm:ss', true).isValid() || (0, moment_1.default)(literal, 'HH:mm', true).isValid();
1112
+ }
1113
+ function isDateTimeLiteral(literal) {
1114
+ return (0, moment_1.default)(literal, 'YYYY-MM-DD HH:mm:ss', true).isValid();
1115
+ }
1116
+ function isDateLiteral(literal) {
1117
+ return (0, moment_1.default)(literal, "YYYY-MM-DD", true).isValid();
1118
+ }
1119
+ function getFunctionName(simpleExprFunction) {
1120
+ var _a, _b;
1121
+ return ((_a = simpleExprFunction.functionCall().pureIdentifier()) === null || _a === void 0 ? void 0 : _a.text.toLowerCase())
1122
+ || ((_b = simpleExprFunction.functionCall().qualifiedIdentifier()) === null || _b === void 0 ? void 0 : _b.text.toLowerCase());
1123
+ }
1124
+ function walkExprListParameters(context, exprList, params) {
1125
+ return exprList.map((expr, paramIndex) => {
1126
+ const exprType = walkExpr(context, expr);
1127
+ const paramType = params.kind == 'FixedLengthParams' ? params.paramsType[paramIndex] : freshVar(params.paramType, params.paramType);
1128
+ context.constraints.push({
1129
+ expression: expr.text,
1130
+ type1: exprType,
1131
+ type2: paramType,
1132
+ mostGeneralType: true
1133
+ });
1134
+ return paramType;
1135
+ });
1136
+ }
1137
+ function walkFunctionParameters(context, simpleExprFunction, params) {
1138
+ var _a, _b;
1139
+ const functionName = getFunctionName(simpleExprFunction);
1140
+ const udfExprList = (_a = simpleExprFunction.functionCall().udfExprList()) === null || _a === void 0 ? void 0 : _a.udfExpr();
1141
+ if (udfExprList) {
1142
+ const paramTypes = udfExprList
1143
+ .filter((undefined, paramIndex) => {
1144
+ return functionName == 'timestampdiff' ? paramIndex != 0 : true; //filter the first parameter of timestampdiff function
1145
+ })
1146
+ .map((inExpr, paramIndex) => {
1147
+ const expr = inExpr.expr();
1148
+ const exprType = walkExpr(context, expr);
1149
+ context.constraints.push({
1150
+ expression: expr.text,
1151
+ type1: exprType,
1152
+ type2: params.kind == 'FixedLengthParams' ? params.paramsType[paramIndex] : freshVar(params.paramType, params.paramType),
1153
+ mostGeneralType: true
1154
+ });
1155
+ return exprType;
1156
+ });
1157
+ return paramTypes;
1158
+ }
1159
+ const exprList = (_b = simpleExprFunction.functionCall().exprList()) === null || _b === void 0 ? void 0 : _b.expr();
1160
+ if (exprList) {
1161
+ const paramTypes = exprList.map((inExpr, paramIndex) => {
1162
+ const inSumExprType = walkExpr(context, inExpr);
1163
+ context.constraints.push({
1164
+ expression: inExpr.text,
1165
+ type1: params.kind == 'FixedLengthParams' ? params.paramsType[paramIndex] : freshVar(params.paramType, params.paramType),
1166
+ type2: inSumExprType,
1167
+ mostGeneralType: true
1168
+ });
1169
+ return inSumExprType;
1170
+ });
1171
+ return paramTypes;
1172
+ }
1173
+ throw Error('Error in walkFunctionParameters');
1174
+ }
1175
+ function walkSubquery(context, queryExpressionParens) {
1176
+ const querySpec = (0, parse_1.getQuerySpecificationsFromSelectStatement)(queryExpressionParens);
1177
+ const subqueryColumns = (0, select_columns_1.getColumnsFrom)(querySpec[0], context.dbSchema);
1178
+ const newContext = Object.assign(Object.assign({}, context), { fromColumns: context.fromColumns.concat(subqueryColumns) });
1179
+ const typeInferResult = walkQuerySpecification(newContext, querySpec[0]);
1180
+ for (let queryIndex = 1; queryIndex < querySpec.length; queryIndex++) { //union (if have any)
1181
+ const unionColumns = (0, select_columns_1.getColumnsFrom)(querySpec[queryIndex], context.dbSchema);
1182
+ const unionNewContext = Object.assign(Object.assign({}, context), { fromColumns: context.fromColumns.concat(unionColumns) });
1183
+ const unionResult = walkQuerySpecification(unionNewContext, querySpec[queryIndex]);
1184
+ typeInferResult.types.forEach((field, fieldIndex) => {
1185
+ context.constraints.push({
1186
+ expression: querySpec[queryIndex].text,
1187
+ type1: typeInferResult.types[fieldIndex],
1188
+ type2: unionResult.types[fieldIndex],
1189
+ mostGeneralType: true
1190
+ });
1191
+ });
1192
+ }
1193
+ //Should retrun the union result type, not the first query from result
1194
+ return typeInferResult;
1195
+ }
1196
+ exports.walkSubquery = walkSubquery;
1196
1197
  //# sourceMappingURL=collect-constraints.js.map