oak-db 1.0.0

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.
@@ -0,0 +1,742 @@
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.SqlTranslator = void 0;
7
+ var assert_1 = __importDefault(require("assert"));
8
+ var lodash_1 = require("lodash");
9
+ var luxon_1 = require("luxon");
10
+ var types_1 = require("oak-domain/lib/types");
11
+ var relation_1 = require("oak-domain/lib/store/relation");
12
+ ;
13
+ ;
14
+ var SqlTranslator = /** @class */ (function () {
15
+ function SqlTranslator(schema) {
16
+ this.schema = this.makeFullSchema(schema);
17
+ }
18
+ SqlTranslator.prototype.makeFullSchema = function (schema2) {
19
+ var schema = (0, lodash_1.cloneDeep)(schema2);
20
+ for (var entity in schema) {
21
+ var _a = schema[entity], attributes = _a.attributes, indexes = _a.indexes;
22
+ // 增加默认的属性
23
+ (0, lodash_1.assign)(attributes, {
24
+ id: {
25
+ type: 'char',
26
+ params: {
27
+ length: 36,
28
+ },
29
+ },
30
+ $$createAt$$: {
31
+ type: 'date',
32
+ notNull: true,
33
+ },
34
+ $$updateAt$$: {
35
+ type: 'date',
36
+ notNull: true,
37
+ },
38
+ $$deleteAt$$: {
39
+ type: 'date',
40
+ },
41
+ $$triggerData$$: {
42
+ type: 'object',
43
+ },
44
+ $$triggerTimestamp$$: {
45
+ type: 'date',
46
+ },
47
+ });
48
+ // 增加默认的索引
49
+ var intrinsticIndexes = [
50
+ {
51
+ name: "".concat(entity, "_create_at"),
52
+ attributes: [{
53
+ name: '$$createAt$$',
54
+ }]
55
+ }, {
56
+ name: "".concat(entity, "_update_at"),
57
+ attributes: [{
58
+ name: '$$updateAt$$',
59
+ }],
60
+ }, {
61
+ name: "".concat(entity, "_trigger_ts"),
62
+ attributes: [{
63
+ name: '$$triggerTimestamp$$',
64
+ }],
65
+ }
66
+ ];
67
+ var _loop_1 = function (attr) {
68
+ if (attributes[attr].type === 'ref') {
69
+ if (!(indexes === null || indexes === void 0 ? void 0 : indexes.find(function (ele) { return ele.attributes[0].name === attr; }))) {
70
+ intrinsticIndexes.push({
71
+ name: "".concat(entity, "_fk_").concat(attr),
72
+ attributes: [{
73
+ name: attr,
74
+ }]
75
+ });
76
+ }
77
+ }
78
+ if (attr === 'entity' && attributes[attr].type === 'varchar') {
79
+ var entityIdDef = attributes.entityId;
80
+ if ((entityIdDef === null || entityIdDef === void 0 ? void 0 : entityIdDef.type) === 'varchar') {
81
+ if (!(indexes === null || indexes === void 0 ? void 0 : indexes.find(function (ele) { var _a; return ele.attributes[0].name === 'entity' && ((_a = ele.attributes[1]) === null || _a === void 0 ? void 0 : _a.name) === 'entityId'; }))) {
82
+ intrinsticIndexes.push({
83
+ name: "".concat(entity, "_fk_entity_entityId"),
84
+ attributes: [{
85
+ name: 'entity',
86
+ }, {
87
+ name: 'entityId',
88
+ }]
89
+ });
90
+ }
91
+ }
92
+ }
93
+ };
94
+ // 增加外键上的索引
95
+ for (var attr in attributes) {
96
+ _loop_1(attr);
97
+ }
98
+ if (indexes) {
99
+ indexes.push.apply(indexes, intrinsticIndexes);
100
+ }
101
+ else {
102
+ (0, lodash_1.assign)(schema[entity], {
103
+ indexes: intrinsticIndexes,
104
+ });
105
+ }
106
+ }
107
+ return schema;
108
+ };
109
+ SqlTranslator.prototype.getStorageName = function (entity) {
110
+ var storageName = this.schema[entity].storageName;
111
+ return (storageName || entity);
112
+ };
113
+ SqlTranslator.prototype.translateInsert = function (entity, data) {
114
+ var _this = this;
115
+ var schema = this.schema;
116
+ var _a = schema[entity], attributes = _a.attributes, _b = _a.storageName, storageName = _b === void 0 ? entity : _b;
117
+ var sql = "insert into `".concat(storageName, "`(");
118
+ var attrs = Object.keys(data[0]).filter(function (ele) { return attributes.hasOwnProperty(ele); });
119
+ attrs.forEach(function (attr, idx) {
120
+ sql += " `".concat(attr, "`");
121
+ if (idx < attrs.length - 1) {
122
+ sql += ',';
123
+ }
124
+ });
125
+ sql += ', `$$createAt$$`, `$$updateAt$$`) values ';
126
+ var now = luxon_1.DateTime.now().toFormat('yyyy-LL-dd HH:mm:ss');
127
+ data.forEach(function (d, dataIndex) {
128
+ sql += '(';
129
+ attrs.forEach(function (attr, attrIdx) {
130
+ var attrDef = attributes[attr];
131
+ var dataType = attrDef.type;
132
+ var value = _this.translateAttrValue(dataType, d[attr]);
133
+ sql += value;
134
+ if (attrIdx < attrs.length - 1) {
135
+ sql += ',';
136
+ }
137
+ });
138
+ sql += ", '".concat(now, "', '").concat(now, "')");
139
+ if (dataIndex < data.length - 1) {
140
+ sql += ',';
141
+ }
142
+ });
143
+ return sql;
144
+ };
145
+ /**
146
+ * analyze the join relations in projection/query/sort
147
+ * 所有的层次关系都当成left join处理,如果有内表为空的情况,请手动处理
148
+ * {
149
+ * b: {
150
+ * name: {
151
+ * $exists: false,
152
+ * }
153
+ * }
154
+ * }
155
+ * 这样的query会把内表为空的行也返回
156
+ * @param param0
157
+ */
158
+ SqlTranslator.prototype.analyzeJoin = function (entity, _a, initialNumber) {
159
+ var _this = this;
160
+ var projection = _a.projection, filter = _a.filter, sorter = _a.sorter, isStat = _a.isStat;
161
+ var schema = this.schema;
162
+ var number = initialNumber || 1;
163
+ var projectionRefAlias = {};
164
+ var filterRefAlias = {};
165
+ var extraWhere = '';
166
+ var alias = "".concat(entity, "_").concat(number++);
167
+ var from = " `".concat(this.getStorageName(entity), "` `").concat(alias, "` ");
168
+ var aliasDict = {
169
+ './': alias,
170
+ };
171
+ var analyzeFilterNode = function (_a) {
172
+ var _b;
173
+ var node = _a.node, path = _a.path, entityName = _a.entityName, alias = _a.alias;
174
+ Object.keys(node).forEach(function (op) {
175
+ var _a, _b;
176
+ if (['$and', '$or'].includes(op)) {
177
+ node[op].forEach(function (subNode) { return analyzeFilterNode({
178
+ node: subNode,
179
+ path: path,
180
+ entityName: entityName,
181
+ alias: alias,
182
+ }); });
183
+ }
184
+ else {
185
+ var rel = (0, relation_1.judgeRelation)(_this.schema, entityName, op);
186
+ if (typeof rel === 'string') {
187
+ var alias2 = void 0;
188
+ var pathAttr = "".concat(path).concat(op, "/");
189
+ if (!aliasDict.hasOwnProperty(pathAttr)) {
190
+ alias2 = "".concat(rel, "_").concat(number++);
191
+ (0, lodash_1.assign)(aliasDict, (_a = {},
192
+ _a[pathAttr] = alias2,
193
+ _a));
194
+ from += " left join `".concat(_this.getStorageName(rel), "` `").concat(alias2, "` on `").concat(alias, "`.`").concat(op, "Id` = `").concat(alias2, "`.`id`");
195
+ }
196
+ else {
197
+ alias2 = aliasDict[pathAttr];
198
+ }
199
+ analyzeFilterNode({
200
+ node: node[op],
201
+ path: pathAttr,
202
+ entityName: rel,
203
+ alias: alias2,
204
+ });
205
+ }
206
+ else if (rel === 2) {
207
+ var alias2 = void 0;
208
+ var pathAttr = "".concat(path).concat(op, "/");
209
+ if (!aliasDict.hasOwnProperty(pathAttr)) {
210
+ alias2 = "".concat(op, "_").concat(number++);
211
+ (0, lodash_1.assign)(aliasDict, (_b = {},
212
+ _b[pathAttr] = alias2,
213
+ _b));
214
+ from += " left join `".concat(_this.getStorageName(op), "` `").concat(alias2, "` on `").concat(alias, "`.`entityId` = `").concat(alias2, "`.`id`");
215
+ extraWhere += "`".concat(alias, "`.`entity` = '").concat(op, "'");
216
+ }
217
+ else {
218
+ alias2 = aliasDict[pathAttr];
219
+ }
220
+ analyzeFilterNode({
221
+ node: node[op],
222
+ path: pathAttr,
223
+ entityName: rel,
224
+ alias: alias2,
225
+ });
226
+ }
227
+ else {
228
+ // 不支持一对多
229
+ (0, assert_1.default)(rel === 0 || rel === 1);
230
+ }
231
+ }
232
+ });
233
+ if (node['#id']) {
234
+ (0, assert_1.default)(!filterRefAlias[node['#id']]);
235
+ (0, lodash_1.assign)(filterRefAlias, (_b = {},
236
+ _b[node['#id']] = alias,
237
+ _b));
238
+ }
239
+ };
240
+ if (filter) {
241
+ analyzeFilterNode({
242
+ node: filter,
243
+ path: './',
244
+ entityName: entity,
245
+ alias: alias,
246
+ });
247
+ }
248
+ var analyzeSortNode = function (_a) {
249
+ var _b, _c;
250
+ var node = _a.node, path = _a.path, entityName = _a.entityName, alias = _a.alias;
251
+ var attr = (0, lodash_1.keys)(node)[0];
252
+ var rel = (0, relation_1.judgeRelation)(_this.schema, entityName, attr);
253
+ if (typeof rel === 'string') {
254
+ var pathAttr = "".concat(path).concat(attr, "/");
255
+ var alias2 = void 0;
256
+ if (!aliasDict.hasOwnProperty(pathAttr)) {
257
+ alias2 = "".concat(rel, "_").concat(number++);
258
+ (0, lodash_1.assign)(aliasDict, (_b = {},
259
+ _b[pathAttr] = alias2,
260
+ _b));
261
+ from += " left join `".concat(_this.getStorageName(rel), "` `").concat(alias2, "` on `").concat(alias, "`.`").concat(attr, "Id` = `").concat(alias2, "`.`id`");
262
+ }
263
+ else {
264
+ alias2 = aliasDict[pathAttr];
265
+ }
266
+ analyzeSortNode({
267
+ node: node[attr],
268
+ path: pathAttr,
269
+ entityName: rel,
270
+ alias: alias2,
271
+ });
272
+ }
273
+ else if (rel === 2) {
274
+ var pathAttr = "".concat(path).concat(attr, "/");
275
+ var alias2 = void 0;
276
+ if (!aliasDict.hasOwnProperty(pathAttr)) {
277
+ alias2 = "".concat(attr, "_").concat(number++);
278
+ (0, lodash_1.assign)(aliasDict, (_c = {},
279
+ _c[pathAttr] = alias2,
280
+ _c));
281
+ from += " left join `".concat(_this.getStorageName(attr), "` `").concat(alias2, "` on `").concat(alias, "`.`entityId` = `").concat(alias2, "`.`id`");
282
+ extraWhere += "`".concat(alias, "`.`entity` = '").concat(attr, "'");
283
+ }
284
+ else {
285
+ alias2 = aliasDict[pathAttr];
286
+ }
287
+ analyzeSortNode({
288
+ node: node[attr],
289
+ path: pathAttr,
290
+ entityName: attr,
291
+ alias: alias2,
292
+ });
293
+ }
294
+ else {
295
+ (0, assert_1.default)(rel === 0 || rel === 1);
296
+ }
297
+ };
298
+ if (sorter) {
299
+ sorter.forEach(function (sortNode) {
300
+ analyzeSortNode({
301
+ node: sortNode.$attr,
302
+ path: './',
303
+ entityName: entity,
304
+ alias: alias,
305
+ });
306
+ });
307
+ }
308
+ var analyzeProjectionNode = function (_a) {
309
+ var _b;
310
+ var node = _a.node, path = _a.path, entityName = _a.entityName, alias = _a.alias;
311
+ var attributes = schema[entityName].attributes;
312
+ Object.keys(node).forEach(function (attr) {
313
+ var _a, _b;
314
+ var rel = (0, relation_1.judgeRelation)(_this.schema, entityName, attr);
315
+ if (typeof rel === 'string') {
316
+ var pathAttr = "".concat(path).concat(attr, "/");
317
+ var alias2 = void 0;
318
+ if (!aliasDict.hasOwnProperty(pathAttr)) {
319
+ alias2 = "".concat(rel, "_").concat(number++);
320
+ (0, lodash_1.assign)(aliasDict, (_a = {},
321
+ _a[pathAttr] = alias2,
322
+ _a));
323
+ from += " left join `".concat(_this.getStorageName(rel), "` `").concat(alias2, "` on `").concat(alias, "`.`").concat(attr, "Id` = `").concat(alias2, "`.`id`");
324
+ }
325
+ else {
326
+ alias2 = aliasDict[pathAttr];
327
+ }
328
+ analyzeProjectionNode({
329
+ node: node[attr],
330
+ path: pathAttr,
331
+ entityName: rel,
332
+ alias: alias2,
333
+ });
334
+ }
335
+ else if (rel === 2) {
336
+ var pathAttr = "".concat(path).concat(attr, "/");
337
+ var alias2 = void 0;
338
+ if (!aliasDict.hasOwnProperty(pathAttr)) {
339
+ alias2 = "".concat(attr, "_").concat(number++);
340
+ (0, lodash_1.assign)(aliasDict, (_b = {},
341
+ _b[pathAttr] = alias2,
342
+ _b));
343
+ from += " left join `".concat(_this.getStorageName(attr), "` `").concat(alias2, "` on `").concat(alias, "`.`entityId` = `").concat(alias2, "`.`id`");
344
+ }
345
+ else {
346
+ alias2 = aliasDict[pathAttr];
347
+ }
348
+ analyzeProjectionNode({
349
+ node: node[attr],
350
+ path: pathAttr,
351
+ entityName: attr,
352
+ alias: alias2,
353
+ });
354
+ extraWhere += "`".concat(alias, "`.`entity` = '").concat(attr, "'");
355
+ }
356
+ });
357
+ if (node['#id']) {
358
+ (0, assert_1.default)(!projectionRefAlias[node['#id']]);
359
+ (0, lodash_1.assign)(projectionRefAlias, (_b = {},
360
+ _b[node['#id']] = alias,
361
+ _b));
362
+ }
363
+ };
364
+ if (projection) {
365
+ analyzeProjectionNode({ node: projection, path: './', entityName: entity, alias: alias });
366
+ }
367
+ return {
368
+ aliasDict: aliasDict,
369
+ from: from,
370
+ projectionRefAlias: projectionRefAlias,
371
+ filterRefAlias: filterRefAlias,
372
+ extraWhere: extraWhere,
373
+ currentNumber: number,
374
+ };
375
+ };
376
+ SqlTranslator.prototype.translateComparison = function (attr, value, type) {
377
+ var SQL_OP = {
378
+ $gt: '>',
379
+ $lt: '<',
380
+ $gte: '>=',
381
+ $lte: '<=',
382
+ $eq: '=',
383
+ $ne: '<>',
384
+ };
385
+ if (Object.keys(SQL_OP).includes(attr)) {
386
+ return " ".concat(SQL_OP[attr], " ").concat(this.translateAttrValue(type, value));
387
+ }
388
+ switch (attr) {
389
+ case '$startsWith': {
390
+ return " like '".concat(value, "%'");
391
+ }
392
+ case '$endsWith': {
393
+ return " like '%".concat(value, "'");
394
+ }
395
+ case '$includes': {
396
+ return " like '%".concat(value, "%'");
397
+ }
398
+ default: {
399
+ throw new Error("unrecoganized comparison operator ".concat(attr));
400
+ }
401
+ }
402
+ };
403
+ SqlTranslator.prototype.translateElement = function (attr, value) {
404
+ (0, assert_1.default)(attr === '$exists'); // only support one operator now
405
+ if (value) {
406
+ return ' is not null';
407
+ }
408
+ return ' is null';
409
+ };
410
+ SqlTranslator.prototype.translateEvaluation = function (attr, value, entity, alias, type, initialNumber, refAlias) {
411
+ switch (attr) {
412
+ case '$text': {
413
+ // fulltext search
414
+ return {
415
+ stmt: this.translateFullTextSearch(value, entity, alias),
416
+ currentNumber: initialNumber,
417
+ };
418
+ }
419
+ case '$in':
420
+ case '$nin': {
421
+ var IN_OP = {
422
+ $in: 'in',
423
+ $nin: 'not in',
424
+ };
425
+ if (value instanceof Array) {
426
+ var values = value.map(function (v) {
427
+ if (['varchar', 'char', 'text', 'nvarchar', 'ref'].includes(type)) {
428
+ return "'".concat(v, "'");
429
+ }
430
+ else {
431
+ return "".concat(v);
432
+ }
433
+ });
434
+ if (values.length > 0) {
435
+ return {
436
+ stmt: " ".concat(IN_OP[attr], "(").concat(values.join(','), ")"),
437
+ currentNumber: initialNumber,
438
+ };
439
+ }
440
+ else {
441
+ if (attr === '$in') {
442
+ return {
443
+ stmt: ' in (null)',
444
+ currentNumber: initialNumber,
445
+ };
446
+ }
447
+ else {
448
+ return {
449
+ stmt: ' is not null',
450
+ currentNumber: initialNumber,
451
+ };
452
+ }
453
+ }
454
+ }
455
+ else {
456
+ // sub query
457
+ var _a = this.translateSelectInner(value.entity, value, initialNumber, refAlias, undefined), subQueryStmt = _a.stmt, currentNumber = _a.currentNumber;
458
+ return {
459
+ stmt: " ".concat(IN_OP[attr], "(").concat(subQueryStmt, ")"),
460
+ currentNumber: currentNumber,
461
+ };
462
+ }
463
+ }
464
+ default: {
465
+ (0, assert_1.default)('$between' === attr);
466
+ var values = value.map(function (v) {
467
+ if (['varchar', 'char', 'text', 'nvarchar', 'ref'].includes(type)) {
468
+ return "'".concat(v, "'");
469
+ }
470
+ else {
471
+ return "".concat(v);
472
+ }
473
+ });
474
+ return {
475
+ stmt: " between ".concat(values[0], " and ").concat(values[1]),
476
+ currentNumber: initialNumber,
477
+ };
478
+ }
479
+ }
480
+ };
481
+ SqlTranslator.prototype.translateFilter = function (entity, selection, aliasDict, filterRefAlias, initialNumber, extraWhere, option) {
482
+ var _this = this;
483
+ var schema = this.schema;
484
+ var filter = selection.filter;
485
+ var currentNumber = initialNumber;
486
+ var translateInner = function (entity2, path, filter2, type) {
487
+ var alias = aliasDict[path];
488
+ var attributes = schema[entity2].attributes;
489
+ var whereText = type ? '' : _this.getDefaultSelectFilter(alias, option);
490
+ if (filter2) {
491
+ var attrs = Object.keys(filter2).filter(function (ele) { return !ele.startsWith('#'); });
492
+ attrs.forEach(function (attr) {
493
+ if (whereText) {
494
+ whereText += ' and ';
495
+ }
496
+ whereText + '(';
497
+ if (['$and', '$or', '$xor', '$not'].includes(attr)) {
498
+ var result = '';
499
+ switch (attr) {
500
+ case '$and':
501
+ case '$or':
502
+ case '$xor': {
503
+ var logicQueries_1 = filter2[attr];
504
+ logicQueries_1.forEach(function (logicQuery, index) {
505
+ var sql = translateInner(entity2, path, logicQuery);
506
+ if (sql) {
507
+ whereText += " (".concat(sql, ")");
508
+ if (index < logicQueries_1.length - 1) {
509
+ whereText += " ".concat(attr.slice(1));
510
+ }
511
+ }
512
+ });
513
+ break;
514
+ }
515
+ default: {
516
+ (0, assert_1.default)(attr === '$not');
517
+ var logicQuery = filter2[attr];
518
+ var sql = translateInner(entity2, path, logicQuery);
519
+ if (sql) {
520
+ whereText += " not (".concat(translateInner(entity2, path, logicQuery), ")");
521
+ break;
522
+ }
523
+ }
524
+ }
525
+ }
526
+ else if (attr.toLowerCase().startsWith(types_1.EXPRESSION_PREFIX)) {
527
+ // expression
528
+ whereText += " (".concat(_this.translateExpression(alias, filter2[attr], filterRefAlias), ")");
529
+ }
530
+ else if (['$gt', '$gte', '$lt', '$lte', '$eq', '$ne', '$startsWith', '$endsWith', '$includes'].includes(attr)) {
531
+ whereText += _this.translateComparison(attr, filter2[attr], type);
532
+ }
533
+ else if (['$exists'].includes(attr)) {
534
+ whereText += _this.translateElement(attr, filter2[attr]);
535
+ }
536
+ else if (['$text', '$in', '$nin', '$between'].includes(attr)) {
537
+ var _a = _this.translateEvaluation(attr, filter2[attr], entity2, alias, type, initialNumber, filterRefAlias), stmt = _a.stmt, cn2 = _a.currentNumber;
538
+ whereText += stmt;
539
+ currentNumber = cn2;
540
+ }
541
+ else {
542
+ var rel = (0, relation_1.judgeRelation)(_this.schema, entity, attr);
543
+ if (rel === 2) {
544
+ whereText += " ".concat(translateInner(attr, "".concat(path).concat(attr, "/"), filter2[attr]));
545
+ }
546
+ else if (typeof rel === 'string') {
547
+ whereText += " ".concat(translateInner(rel, "".concat(path).concat(attr, "/"), filter2[attr]));
548
+ }
549
+ else {
550
+ (0, assert_1.default)(attributes.hasOwnProperty(attr), "\u975E\u6CD5\u7684\u5C5E\u6027".concat(attr));
551
+ var type2 = attributes[attr].type;
552
+ // assert (type2 !== 'ref');
553
+ if (typeof filter2[attr] === 'object' && Object.keys(filter2[attr])[0] && Object.keys(filter2[attr])[0].startsWith('$')) {
554
+ whereText += " `".concat(alias, "`.`").concat(attr, "` ").concat(translateInner(entity2, path, filter2[attr], type2));
555
+ }
556
+ else {
557
+ whereText += " `".concat(alias, "`.`").concat(attr, "` = ").concat(_this.translateAttrValue(type2, filter2[attr]));
558
+ }
559
+ }
560
+ }
561
+ whereText + ')';
562
+ });
563
+ }
564
+ if (!whereText) {
565
+ whereText = 'true'; // 如果为空就赋一个永真条件,以便处理and
566
+ }
567
+ return whereText;
568
+ };
569
+ var where = translateInner(entity, './', filter);
570
+ if (extraWhere && where) {
571
+ return {
572
+ stmt: "".concat(extraWhere, " and ").concat(where),
573
+ currentNumber: currentNumber,
574
+ };
575
+ }
576
+ return {
577
+ stmt: extraWhere || where,
578
+ currentNumber: currentNumber,
579
+ };
580
+ };
581
+ SqlTranslator.prototype.translateSorter = function (entity, sorter, aliasDict) {
582
+ var _this = this;
583
+ var translateInner = function (entity2, sortAttr, path) {
584
+ (0, assert_1.default)(Object.keys(sortAttr).length === 1);
585
+ var attr = Object.keys(sortAttr)[0];
586
+ var alias = aliasDict[path];
587
+ if (attr.toLocaleLowerCase().startsWith(types_1.EXPRESSION_PREFIX)) {
588
+ return _this.translateExpression(alias, sortAttr[attr], {});
589
+ }
590
+ else if (sortAttr[attr] === 1) {
591
+ return "`".concat(alias, "`.`").concat(attr, "`");
592
+ }
593
+ else {
594
+ var rel = (0, relation_1.judgeRelation)(_this.schema, entity2, attr);
595
+ if (typeof rel === 'string') {
596
+ return translateInner(rel, sortAttr[attr], "".concat(path).concat(attr, "/"));
597
+ }
598
+ else {
599
+ (0, assert_1.default)(rel === 2);
600
+ return translateInner(attr, sortAttr[attr], "".concat(path).concat(attr, "/"));
601
+ }
602
+ }
603
+ };
604
+ var sortText = '';
605
+ sorter.forEach(function (sortNode, index) {
606
+ var $attr = sortNode.$attr, $direction = sortNode.$direction;
607
+ sortText += translateInner(entity, $attr, './');
608
+ if ($direction) {
609
+ sortText += " ".concat($direction);
610
+ }
611
+ if (index < sorter.length - 1) {
612
+ sortText += ',';
613
+ }
614
+ });
615
+ return sortText;
616
+ };
617
+ SqlTranslator.prototype.translateProjection = function (entity, projection, aliasDict, projectionRefAlias) {
618
+ var _this = this;
619
+ var schema = this.schema;
620
+ var translateInner = function (entity2, projection2, path) {
621
+ var alias = aliasDict[path];
622
+ var attributes = schema[entity2].attributes;
623
+ var projText = '';
624
+ var prefix = path.slice(2).replace(/\//g, '.');
625
+ var attrs = Object.keys(projection2).filter(function (attr) {
626
+ if (attr.toLowerCase().startsWith(types_1.EXPRESSION_PREFIX)) {
627
+ return true;
628
+ }
629
+ var rel = (0, relation_1.judgeRelation)(_this.schema, entity2, attr);
630
+ return [1, 2].includes(rel) || typeof rel === 'string';
631
+ });
632
+ attrs.forEach(function (attr, idx) {
633
+ if (attr.toLowerCase().startsWith(types_1.EXPRESSION_PREFIX)) {
634
+ var exprText = _this.translateExpression(alias, projection2[attr], projectionRefAlias);
635
+ projText += " ".concat(exprText, " as ").concat(prefix).concat(attr);
636
+ }
637
+ else {
638
+ var rel = (0, relation_1.judgeRelation)(_this.schema, entity2, attr);
639
+ if (typeof rel === 'string') {
640
+ projText += translateInner(rel, projection2[attr], "".concat(path).concat(attr, "/"));
641
+ }
642
+ else if (rel === 2) {
643
+ projText += translateInner(attr, projection2[attr], "".concat(path).concat(attr, "/"));
644
+ }
645
+ else if (rel === 1) {
646
+ var type = attributes[attr].type;
647
+ if (projection2[attr] === 1) {
648
+ projText += " ".concat(_this.translateAttrProjection(type, alias, attr), " as `").concat(prefix).concat(attr, "`");
649
+ }
650
+ else {
651
+ (0, assert_1.default)(typeof projection2 === 'string');
652
+ projText += " ".concat(_this.translateAttrProjection(type, alias, attr), " as `").concat(prefix).concat(projection2[attr], "`");
653
+ }
654
+ }
655
+ }
656
+ if (idx < attrs.length - 1) {
657
+ projText += ',';
658
+ }
659
+ });
660
+ return projText;
661
+ };
662
+ return translateInner(entity, projection, './');
663
+ };
664
+ SqlTranslator.prototype.translateSelectInner = function (entity, selection, initialNumber, refAlias, option) {
665
+ var data = selection.data, filter = selection.filter, sorter = selection.sorter, indexFrom = selection.indexFrom, count = selection.count;
666
+ var _a = this.analyzeJoin(entity, {
667
+ projection: data,
668
+ filter: filter,
669
+ sorter: sorter,
670
+ }, initialNumber), fromText = _a.from, aliasDict = _a.aliasDict, projectionRefAlias = _a.projectionRefAlias, extraWhere = _a.extraWhere, filterRefAlias = _a.filterRefAlias, currentNumber = _a.currentNumber;
671
+ (0, assert_1.default)((0, lodash_1.intersection)((0, lodash_1.keys)(refAlias), (0, lodash_1.keys)(filterRefAlias)).length === 0, 'filter中的#node结点定义有重复');
672
+ (0, lodash_1.assign)(refAlias, filterRefAlias);
673
+ var projText = this.translateProjection(entity, data, aliasDict, projectionRefAlias);
674
+ var _b = this.translateFilter(entity, selection, aliasDict, refAlias, currentNumber, extraWhere, option), filterText = _b.stmt, currentNumber2 = _b.currentNumber;
675
+ var sorterText = sorter && this.translateSorter(entity, sorter, aliasDict);
676
+ return {
677
+ stmt: this.populateSelectStmt(projText, fromText, selection, aliasDict, filterText, sorterText, indexFrom, count, option),
678
+ currentNumber: currentNumber2,
679
+ };
680
+ };
681
+ SqlTranslator.prototype.translateSelect = function (entity, selection, option) {
682
+ var stmt = this.translateSelectInner(entity, selection, 1, {}, option).stmt;
683
+ return stmt;
684
+ };
685
+ SqlTranslator.prototype.translateCount = function (entity, selection, option) {
686
+ var filter = selection.filter, count = selection.count;
687
+ var _a = this.analyzeJoin(entity, {
688
+ filter: filter,
689
+ }), fromText = _a.from, aliasDict = _a.aliasDict, extraWhere = _a.extraWhere, filterRefAlias = _a.filterRefAlias, currentNumber = _a.currentNumber;
690
+ var projText = 'count(1)';
691
+ var filterText = this.translateFilter(entity, selection, aliasDict, filterRefAlias, currentNumber, extraWhere, option).stmt;
692
+ if (count) {
693
+ var subQuerySql = this.populateSelectStmt('1', fromText, Object.assign({}, selection, { indexFrom: 0 }), aliasDict, filterText, undefined, undefined, undefined, option);
694
+ return "select count(1) from (".concat(subQuerySql, ")");
695
+ }
696
+ return this.populateSelectStmt(projText, fromText, selection, aliasDict, filterText, undefined, undefined, undefined, option);
697
+ };
698
+ SqlTranslator.prototype.translateRemove = function (entity, operation, option) {
699
+ var filter = operation.filter, sorter = operation.sorter, indexFrom = operation.indexFrom, count = operation.count;
700
+ var _a = this.analyzeJoin(entity, { filter: filter, sorter: sorter }), aliasDict = _a.aliasDict, filterRefAlias = _a.filterRefAlias, extraWhere = _a.extraWhere, fromText = _a.from, currentNumber = _a.currentNumber;
701
+ var alias = aliasDict['./'];
702
+ var filterText = this.translateFilter(entity, operation, aliasDict, filterRefAlias, currentNumber, extraWhere).stmt;
703
+ var sorterText = sorter && sorter.length > 0 ? this.translateSorter(entity, sorter, aliasDict) : undefined;
704
+ return this.populateRemoveStmt(alias, fromText, aliasDict, filterText, sorterText, indexFrom, count, option);
705
+ };
706
+ SqlTranslator.prototype.translateUpdate = function (entity, operation, option) {
707
+ var attributes = this.schema[entity].attributes;
708
+ var filter = operation.filter, sorter = operation.sorter, indexFrom = operation.indexFrom, count = operation.count, data = operation.data;
709
+ var _a = this.analyzeJoin(entity, { filter: filter, sorter: sorter }), aliasDict = _a.aliasDict, filterRefAlias = _a.filterRefAlias, extraWhere = _a.extraWhere, fromText = _a.from, currentNumber = _a.currentNumber;
710
+ var alias = aliasDict['./'];
711
+ var updateText = '';
712
+ for (var attr in data) {
713
+ if (updateText) {
714
+ updateText += ',';
715
+ }
716
+ (0, assert_1.default)(attributes.hasOwnProperty(attr) && attributes[attr].type !== 'ref');
717
+ var value = this.translateAttrValue(attributes[attr].type, data[attr]);
718
+ updateText += "`".concat(alias, "`.`").concat(attr, "` = ").concat(value);
719
+ }
720
+ var filterText = this.translateFilter(entity, operation, aliasDict, filterRefAlias, currentNumber, extraWhere).stmt;
721
+ var sorterText = sorter && this.translateSorter(entity, sorter, aliasDict);
722
+ return this.populateUpdateStmt(updateText, fromText, aliasDict, filterText, sorterText, indexFrom, count, option);
723
+ };
724
+ SqlTranslator.prototype.translateDestroyEntity = function (entity, truncate) {
725
+ var schema = this.schema;
726
+ var _a = schema[entity], _b = _a.storageName, storageName = _b === void 0 ? entity : _b, view = _a.view;
727
+ var sql;
728
+ if (view) {
729
+ sql = "drop view if exists `".concat(storageName, "`");
730
+ }
731
+ else {
732
+ sql = truncate ? "truncate table `".concat(storageName, "`") : "drop table if exists `".concat(storageName, "`");
733
+ }
734
+ return sql;
735
+ };
736
+ SqlTranslator.prototype.escapeStringValue = function (value) {
737
+ var result = "'".concat(value.replace(/'/g, '\\\''), "'");
738
+ return result;
739
+ };
740
+ return SqlTranslator;
741
+ }());
742
+ exports.SqlTranslator = SqlTranslator;