@gingkoo/pandora-metabase 1.0.26 → 1.0.28

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 (66) hide show
  1. package/lib/cjs/common/SplitView/index.js +11 -12
  2. package/lib/cjs/components/dialog/custom-column/expression-editor.js +1 -2
  3. package/lib/cjs/components/dialog/custom-column/tokenizedI-input.js +1 -2
  4. package/lib/cjs/components/dialog/expression/index.js +11 -12
  5. package/lib/cjs/components/dialog/formula-list/index.js +53 -43
  6. package/lib/cjs/components/dialog/index.js +2 -2
  7. package/lib/cjs/components/dialog/select-column/index.js +4 -4
  8. package/lib/cjs/components/dialog/select-column-multiple/index.js +7 -7
  9. package/lib/cjs/components/dialog/select-join-column/index.js +4 -0
  10. package/lib/cjs/components/dialog/select-permission-table/index.js +2 -2
  11. package/lib/cjs/components/dialog/select-table/index.js +7 -7
  12. package/lib/cjs/components/icons.js +36 -36
  13. package/lib/cjs/components/metabase/index.js +41 -12
  14. package/lib/cjs/components/metabase/index.less +3 -0
  15. package/lib/cjs/components/modules/components/Wrapper.js +6 -6
  16. package/lib/cjs/components/modules/components/item-name.d.ts +7 -0
  17. package/lib/cjs/components/modules/components/item-name.js +34 -0
  18. package/lib/cjs/components/modules/components/meta-icon.js +6 -0
  19. package/lib/cjs/components/modules/custom-column.js +25 -25
  20. package/lib/cjs/components/modules/filter.js +2 -2
  21. package/lib/cjs/components/modules/join-data.js +206 -80
  22. package/lib/cjs/components/modules/permission-table.js +24 -10
  23. package/lib/cjs/components/modules/sort.js +17 -13
  24. package/lib/cjs/components/modules/summarize/group-by.js +90 -38
  25. package/lib/cjs/components/modules/summarize/select-index.js +84 -38
  26. package/lib/cjs/components/modules/table-data.js +14 -6
  27. package/lib/cjs/components/popup.js +1 -2
  28. package/lib/cjs/hooks/use-state.js +58 -65
  29. package/lib/cjs/index.js +1 -2
  30. package/lib/cjs/locale/en.js +5 -2
  31. package/lib/cjs/locale/zh.js +5 -2
  32. package/lib/cjs/utils/transformSql.d.ts +6 -0
  33. package/lib/cjs/utils/transformSql.js +968 -0
  34. package/lib/cjs/utils.d.ts +7 -1
  35. package/lib/cjs/utils.js +112 -15
  36. package/lib/es/common/SplitView/index.js +10 -10
  37. package/lib/es/components/dialog/expression/index.js +10 -10
  38. package/lib/es/components/dialog/formula-list/index.js +54 -44
  39. package/lib/es/components/dialog/select-column/index.js +4 -4
  40. package/lib/es/components/dialog/select-column-multiple/index.js +7 -7
  41. package/lib/es/components/dialog/select-join-column/index.js +4 -0
  42. package/lib/es/components/dialog/select-permission-table/index.js +2 -2
  43. package/lib/es/components/dialog/select-table/index.js +7 -7
  44. package/lib/es/components/icons.js +36 -36
  45. package/lib/es/components/metabase/index.js +42 -13
  46. package/lib/es/components/metabase/index.less +3 -0
  47. package/lib/es/components/modules/components/Wrapper.js +6 -6
  48. package/lib/es/components/modules/components/item-name.d.ts +7 -0
  49. package/lib/es/components/modules/components/item-name.js +28 -0
  50. package/lib/es/components/modules/components/meta-icon.js +6 -0
  51. package/lib/es/components/modules/custom-column.js +26 -26
  52. package/lib/es/components/modules/filter.js +2 -2
  53. package/lib/es/components/modules/join-data.js +207 -81
  54. package/lib/es/components/modules/permission-table.js +24 -10
  55. package/lib/es/components/modules/sort.js +18 -14
  56. package/lib/es/components/modules/summarize/group-by.js +92 -40
  57. package/lib/es/components/modules/summarize/select-index.js +86 -40
  58. package/lib/es/components/modules/table-data.js +14 -6
  59. package/lib/es/hooks/use-state.js +58 -65
  60. package/lib/es/locale/en.js +5 -2
  61. package/lib/es/locale/zh.js +5 -2
  62. package/lib/es/utils/transformSql.d.ts +6 -0
  63. package/lib/es/utils/transformSql.js +961 -0
  64. package/lib/es/utils.d.ts +7 -1
  65. package/lib/es/utils.js +102 -4
  66. package/package.json +1 -1
@@ -0,0 +1,968 @@
1
+ "use strict";
2
+
3
+ var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
4
+ Object.defineProperty(exports, "__esModule", {
5
+ value: true
6
+ });
7
+ exports.transformSql = void 0;
8
+ var _toConsumableArray2 = _interopRequireDefault(require("@babel/runtime/helpers/esm/toConsumableArray"));
9
+ var _objectSpread2 = _interopRequireDefault(require("@babel/runtime/helpers/esm/objectSpread2"));
10
+ var _objectWithoutProperties2 = _interopRequireDefault(require("@babel/runtime/helpers/esm/objectWithoutProperties"));
11
+ var _excluded = ["children"];
12
+ var procEnum = {
13
+ mysql: 'mysql',
14
+ oracle: 'oracle',
15
+ sqlserver: 'sqlserver'
16
+ };
17
+ var MetabaseTypeEnum = {
18
+ data: 'data',
19
+ joinData: 'joinData',
20
+ customColumn: 'customColumn',
21
+ filter: 'filter',
22
+ summarize: 'summarize',
23
+ sort: 'sort',
24
+ rowLimit: 'rowLimit',
25
+ union: 'union',
26
+ permissionTable: 'permissionTable'
27
+ };
28
+ // 数据基础类型
29
+ var BlockTypeEnum = {
30
+ joinDefault: 'joinDefault',
31
+ // 简单的表达式
32
+ expression: 'expression',
33
+ // 表达式
34
+ operator: 'operator',
35
+ // 操作符
36
+ field: 'field',
37
+ // 字段
38
+ inputNumber: 'inputNumber',
39
+ // 数字输入框
40
+ inputString: 'inputString',
41
+ // 字符串输入框
42
+ constant: 'constant',
43
+ // 常量
44
+ inputStringList: 'inputStringList',
45
+ // 多个字符串输入框
46
+ inputNumberList: 'inputNumberList',
47
+ // 多个数字输入框
48
+ unknown: 'unknown',
49
+ // 未知
50
+ notExists: 'notExists',
51
+ exists: 'exists',
52
+ FORMULA: 'FORMULA',
53
+ collection: 'collection'
54
+ };
55
+ var SummarizeAlias = 'source';
56
+ var SQL_GROUP_TYPE = {
57
+ NUMBER: 'number',
58
+ STRING: 'string',
59
+ DATE: 'date'
60
+ };
61
+ var SQL_COLUMN_TYPE = {
62
+ STRING: 'STRING',
63
+ DATE: 'DATE',
64
+ FLOAT: 'FLOAT',
65
+ LONG: 'LONG',
66
+ CURRENCY: 'CURRENCY'
67
+ };
68
+ var DATE_GROUP = [SQL_COLUMN_TYPE.DATE];
69
+ var NUMBER_GROUP = [SQL_COLUMN_TYPE.FLOAT, SQL_COLUMN_TYPE.LONG, SQL_COLUMN_TYPE.CURRENCY];
70
+ var STRING_GROUP = [SQL_COLUMN_TYPE.STRING];
71
+ var _flatArr2 = function _flatArr(data, arr) {
72
+ var children = data.children,
73
+ res = (0, _objectWithoutProperties2["default"])(data, _excluded);
74
+ arr.push(res);
75
+ if (children) {
76
+ _flatArr2(children, arr);
77
+ }
78
+ };
79
+ var _recursionArr2 = function _recursionArr(arr) {
80
+ var obj = (0, _objectSpread2["default"])({}, arr[0]);
81
+ if (arr.length > 1) {
82
+ obj.children = _recursionArr2(arr.slice(1));
83
+ }
84
+ return obj;
85
+ };
86
+ var _handleBaseType2Sql9 = function _handleBaseType2Sql(list) {
87
+ var db = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : procEnum.mysql;
88
+ var sql = '';
89
+ var constants = [];
90
+ var sql_items = []; // 这个是 给 list 单一类型用的,字符串输入框 类型也不加''
91
+ if (!Array.isArray(list)) {
92
+ return {
93
+ sql: sql,
94
+ sql_items: sql_items,
95
+ constants: constants
96
+ };
97
+ }
98
+ list.forEach(function (item) {
99
+ var _condition_, _condition_2;
100
+ var type = item.type;
101
+ if (type === BlockTypeEnum.unknown) {}
102
+ if (type === BlockTypeEnum.operator) {
103
+ sql += " ".concat(item.val);
104
+ sql_items.push(item.val);
105
+ }
106
+ if (type === BlockTypeEnum.field) {
107
+ var fileName = item.fieldName;
108
+ if (item.tableAlias === SummarizeAlias && item.fieldAlias) {
109
+ fileName = item.fieldAlias;
110
+ }
111
+ sql += " ".concat(item.tableAlias, ".").concat(fileName);
112
+ sql_items.push("".concat(item.tableAlias, ".").concat(fileName));
113
+ }
114
+ if (type === BlockTypeEnum.inputNumber) {
115
+ sql += " ".concat(item.val);
116
+ sql_items.push("".concat(item.val));
117
+ }
118
+ if (type === BlockTypeEnum.inputString) {
119
+ if (item.val && (/^'.*'$/.test(item.val) || /^".*"$/.test(item.val))) {
120
+ sql += " ".concat(item.val);
121
+ } else {
122
+ sql += " '".concat(item.val, "'");
123
+ }
124
+ sql_items.push("".concat(item.val));
125
+ }
126
+ if (type === BlockTypeEnum.constant) {
127
+ sql += " ".concat(item.val);
128
+ sql_items.push("".concat(item.val));
129
+ constants.push(item.val);
130
+ }
131
+ if (type === BlockTypeEnum.inputStringList) {
132
+ // 这个如果存在 list 数组中,那么 list 数组种 只能有他,因为他太特殊了,现在就表达式在用
133
+ if (Array.isArray(item.val) && item.val.length) {
134
+ item.val.forEach(function (v) {
135
+ // 这里虽然是字符串 但是不加 ''了 因为他太特殊了 不通用
136
+ sql_items.push("".concat(v));
137
+ });
138
+ }
139
+ }
140
+ if (type === BlockTypeEnum.inputNumberList) {
141
+ // 这个如果存在 list 数组中,那么 list 数组种 只能有他,因为他太特殊了,现在就表达式在用
142
+ if (Array.isArray(item.val) && item.val.length) {
143
+ item.val.forEach(function (v) {
144
+ // 这里虽然是字符串 但是不加 ''了 因为他太特殊了 不通用
145
+ sql_items.push("".concat(v));
146
+ });
147
+ }
148
+ }
149
+ if (type === BlockTypeEnum.joinDefault) {
150
+ var lhs = item.lhs,
151
+ rhs = item.rhs;
152
+ // 他很特殊 左边里面只有一种类型 右边面只有一种类型
153
+ var _handleBaseType2Sql2 = _handleBaseType2Sql9(lhs, db),
154
+ leftSql = _handleBaseType2Sql2.sql,
155
+ leftSqlItems = _handleBaseType2Sql2.sql_items,
156
+ joinDefaultLeftConstants = _handleBaseType2Sql2.constants;
157
+ var _handleBaseType2Sql3 = _handleBaseType2Sql9(rhs, db),
158
+ rightSql = _handleBaseType2Sql3.sql,
159
+ rightSqlItems = _handleBaseType2Sql3.sql_items,
160
+ joinDefaultRightConstants = _handleBaseType2Sql3.constants;
161
+ constants.push.apply(constants, (0, _toConsumableArray2["default"])(joinDefaultLeftConstants));
162
+ constants.push.apply(constants, (0, _toConsumableArray2["default"])(joinDefaultRightConstants));
163
+ var left_condition = leftSql;
164
+ var right_condition = rightSql;
165
+ if (leftSqlItems.length > 1) {
166
+ // 多个肯定是字段
167
+ if (db === procEnum.mysql) {
168
+ left_condition = "CONCAT(".concat(leftSqlItems.join(','), ")");
169
+ }
170
+ if (db === procEnum.oracle) {
171
+ left_condition = "".concat(leftSqlItems.join(' || '));
172
+ }
173
+ if (db === procEnum.sqlserver) {
174
+ left_condition = "".concat(leftSqlItems.join(' + '));
175
+ }
176
+ }
177
+ if (rightSqlItems.length > 1) {
178
+ // 多个肯定是字段
179
+ if (db === procEnum.mysql) {
180
+ right_condition = "CONCAT(".concat(rightSqlItems.join(','), ")");
181
+ }
182
+ if (db === procEnum.oracle) {
183
+ right_condition = "".concat(rightSqlItems.join(' || '));
184
+ }
185
+ if (db === procEnum.sqlserver) {
186
+ right_condition = "".concat(rightSqlItems.join(' + '));
187
+ }
188
+ }
189
+ sql += " ".concat(left_condition, " = ").concat(right_condition);
190
+ }
191
+ if (type === BlockTypeEnum.expression) {
192
+ var _lhs = item.lhs,
193
+ _rhs = item.rhs,
194
+ condition = item.condition,
195
+ database_type = item.database_type,
196
+ formula = item.formula;
197
+ var _handleBaseType2Sql4 = _handleBaseType2Sql9(_lhs, db),
198
+ _leftSql = _handleBaseType2Sql4.sql,
199
+ _leftSqlItems = _handleBaseType2Sql4.sql_items,
200
+ _joinDefaultLeftConstants = _handleBaseType2Sql4.constants;
201
+ var _handleBaseType2Sql5 = _handleBaseType2Sql9(_rhs, db),
202
+ _rightSql = _handleBaseType2Sql5.sql,
203
+ _rightSqlItems = _handleBaseType2Sql5.sql_items,
204
+ _joinDefaultRightConstants = _handleBaseType2Sql5.constants;
205
+ constants.push.apply(constants, (0, _toConsumableArray2["default"])(_joinDefaultLeftConstants));
206
+ constants.push.apply(constants, (0, _toConsumableArray2["default"])(_joinDefaultRightConstants));
207
+ var _left_condition = _leftSql;
208
+ var _right_condition = '';
209
+ if (_leftSqlItems.length > 1) {
210
+ // 多个肯定是字段
211
+ if (db === procEnum.mysql) {
212
+ _left_condition = "CONCAT(".concat(_leftSqlItems.join(','), ")");
213
+ }
214
+ if (db === procEnum.oracle) {
215
+ _left_condition = "".concat(_leftSqlItems.join(' || '));
216
+ }
217
+ if (db === procEnum.sqlserver) {
218
+ _left_condition = "".concat(_leftSqlItems.join(' + '));
219
+ }
220
+ }
221
+ if (formula && formula.type && formula.params) {
222
+ // 目前只有一个 SUBSTR, 也不想再加函数了,函数不在这里加
223
+ var formulaType = formula.type;
224
+ if (db === procEnum.sqlserver && formulaType === 'SUBSTR') {
225
+ formulaType = 'SUBSTRING';
226
+ }
227
+ _left_condition = "".concat(formulaType, "(").concat(formula.params.map(function (it, i) {
228
+ if (!i) {
229
+ // 字段
230
+ return _left_condition;
231
+ } else {
232
+ return it;
233
+ }
234
+ }).join(', '), ")");
235
+ }
236
+ function getGroupType(database_type) {
237
+ var group = SQL_GROUP_TYPE.STRING;
238
+ if (~NUMBER_GROUP.indexOf(database_type)) {
239
+ group = SQL_GROUP_TYPE.NUMBER;
240
+ }
241
+ if (~DATE_GROUP.indexOf(database_type)) {
242
+ group = SQL_GROUP_TYPE.DATE;
243
+ }
244
+ return group;
245
+ }
246
+ var group = getGroupType(database_type);
247
+ if (group === SQL_GROUP_TYPE.STRING) {
248
+ var condition_1 = (_rightSqlItems === null || _rightSqlItems === void 0 ? void 0 : _rightSqlItems[0]) || '';
249
+ switch (condition) {
250
+ // string
251
+ case '等于':
252
+ _right_condition = "= ".concat(_rightSql);
253
+ break;
254
+ case '不等于':
255
+ _right_condition = "!= ".concat(_rightSql);
256
+ break;
257
+ case '包含':
258
+ // 去掉引号
259
+ _right_condition = "LIKE '%".concat(condition_1, "%'");
260
+ break;
261
+ case '不包含':
262
+ _right_condition = "NOT LIKE '%".concat(condition_1, "%'");
263
+ break;
264
+ case '为空':
265
+ _right_condition = "IS NULL";
266
+ break;
267
+ case '不为空':
268
+ _right_condition = "IS NOT NULL";
269
+ break;
270
+ case '以...开始':
271
+ _right_condition = "LIKE '".concat(condition_1, "%'");
272
+ break;
273
+ case '以...结束':
274
+ _right_condition = "LIKE '%".concat(condition_1, "'");
275
+ break;
276
+ case '不以...开始':
277
+ _right_condition = "NOT LIKE '".concat(condition_1, "%'");
278
+ break;
279
+ case '不以...结束':
280
+ _right_condition = "NOT LIKE '%".concat(condition_1, "'");
281
+ break;
282
+ case 'In':
283
+ condition_1 = (_condition_ = condition_1) === null || _condition_ === void 0 || (_condition_ = _condition_.split(',')) === null || _condition_ === void 0 || (_condition_ = _condition_.map(function (v) {
284
+ var _v;
285
+ v = (_v = v) === null || _v === void 0 ? void 0 : _v.trim();
286
+ // 如果已经加了引号
287
+ if (v && (/^'.*'$/.test(v) || /^".*"$/.test(v))) {
288
+ return "".concat(v);
289
+ } else {
290
+ return "'".concat(v, "'");
291
+ }
292
+ })) === null || _condition_ === void 0 ? void 0 : _condition_.join(',');
293
+ _right_condition = "IN (".concat(condition_1, ")");
294
+ break;
295
+ case 'Not In':
296
+ condition_1 = (_condition_2 = condition_1) === null || _condition_2 === void 0 || (_condition_2 = _condition_2.split(',')) === null || _condition_2 === void 0 || (_condition_2 = _condition_2.map(function (v) {
297
+ var _v2;
298
+ v = (_v2 = v) === null || _v2 === void 0 ? void 0 : _v2.trim();
299
+ if (v && (/^'.*'$/.test(v) || /^".*"$/.test(v))) {
300
+ return "".concat(v);
301
+ } else {
302
+ return "'".concat(v, "'");
303
+ }
304
+ })) === null || _condition_2 === void 0 ? void 0 : _condition_2.join(',');
305
+ _right_condition = "NOT IN (".concat(condition_1, ")");
306
+ break;
307
+ case '正则匹配':
308
+ if (db === procEnum.mysql) {
309
+ _right_condition = "REGEXP '".concat(condition_1, "'");
310
+ }
311
+ if (db === procEnum.oracle) {
312
+ _right_condition = "REGEXP_LIKE(".concat(_left_condition, ", '").concat(condition_1, "')");
313
+ _left_condition = '';
314
+ }
315
+ if (db === procEnum.sqlserver) {
316
+ _right_condition = "PATINDEX('".concat(condition_1, "', ").concat(_left_condition, ") = 1");
317
+ _left_condition = '';
318
+ }
319
+ break;
320
+ }
321
+ }
322
+ if (group === SQL_GROUP_TYPE.NUMBER) {
323
+ var _condition_3 = (_rightSqlItems === null || _rightSqlItems === void 0 ? void 0 : _rightSqlItems[0]) || '';
324
+ var condition_2 = (_rightSqlItems === null || _rightSqlItems === void 0 ? void 0 : _rightSqlItems[1]) || '';
325
+ switch (condition) {
326
+ // number
327
+ case '等于':
328
+ _right_condition = "= ".concat(_condition_3);
329
+ break;
330
+ case '不等于':
331
+ _right_condition = "!= ".concat(_condition_3);
332
+ break;
333
+ case '大于':
334
+ _right_condition = "> ".concat(_condition_3);
335
+ break;
336
+ case '小于':
337
+ _right_condition = "< ".concat(_condition_3);
338
+ break;
339
+ case '介于之间':
340
+ _right_condition = "BETWEEN ".concat(_condition_3, " AND ").concat(condition_2);
341
+ break;
342
+ case '大于或等于':
343
+ _right_condition = ">= ".concat(_condition_3);
344
+ break;
345
+ case '小于或等于':
346
+ _right_condition = "<= ".concat(_condition_3);
347
+ break;
348
+ case '为空':
349
+ _right_condition = "IS NULL";
350
+ break;
351
+ case '不为空':
352
+ _right_condition = "IS NOT NULL";
353
+ break;
354
+ case '以...开始':
355
+ if (db === procEnum.mysql) {
356
+ _right_condition = "CAST(".concat(_left_condition, " AS CHAR) LIKE '").concat(_condition_3, "%'");
357
+ _left_condition = '';
358
+ }
359
+ if (db === procEnum.oracle) {
360
+ _right_condition = "TO_CHAR(".concat(_left_condition, ") LIKE '").concat(_condition_3, "%'");
361
+ _left_condition = '';
362
+ }
363
+ if (db === procEnum.sqlserver) {
364
+ _right_condition = "CONVERT(VARCHAR, ".concat(_left_condition, ") LIKE '").concat(_condition_3, "%'");
365
+ _left_condition = '';
366
+ }
367
+ break;
368
+ case '以...结束':
369
+ if (db === procEnum.mysql) {
370
+ _right_condition = "CAST(".concat(_left_condition, " AS CHAR) LIKE '%").concat(_condition_3, "'");
371
+ _left_condition = '';
372
+ }
373
+ if (db === procEnum.oracle) {
374
+ _right_condition = "TO_CHAR(".concat(_left_condition, ") LIKE '%").concat(_condition_3, "'");
375
+ _left_condition = '';
376
+ }
377
+ if (db === procEnum.sqlserver) {
378
+ _right_condition = "CONVERT(VARCHAR, ".concat(_left_condition, ") LIKE '%").concat(_condition_3, "'");
379
+ _left_condition = '';
380
+ }
381
+ break;
382
+ case '不以...开始':
383
+ if (db === procEnum.mysql) {
384
+ _right_condition = "CAST(".concat(_left_condition, " AS CHAR) NOT LIKE '").concat(_condition_3, "%'");
385
+ _left_condition = '';
386
+ }
387
+ if (db === procEnum.oracle) {
388
+ _right_condition = "TO_CHAR(".concat(_left_condition, ") NOT LIKE '").concat(_condition_3, "%'");
389
+ _left_condition = '';
390
+ }
391
+ if (db === procEnum.sqlserver) {
392
+ _right_condition = "CONVERT(VARCHAR, ".concat(_left_condition, ") NOT LIKE '").concat(_condition_3, "%'");
393
+ _left_condition = '';
394
+ }
395
+ break;
396
+ case '不以...结束':
397
+ if (db === procEnum.mysql) {
398
+ _right_condition = "CAST(".concat(_left_condition, " AS CHAR) NOT LIKE '%").concat(_condition_3, "'");
399
+ _left_condition = '';
400
+ }
401
+ if (db === procEnum.oracle) {
402
+ _right_condition = "TO_CHAR(".concat(_left_condition, ") NOT LIKE '%").concat(_condition_3, "'");
403
+ _left_condition = '';
404
+ }
405
+ if (db === procEnum.sqlserver) {
406
+ _right_condition = "CONVERT(VARCHAR, ".concat(_left_condition, ") NOT LIKE '%").concat(_condition_3, "'");
407
+ _left_condition = '';
408
+ }
409
+ break;
410
+ case 'In':
411
+ _right_condition = "IN (".concat(_condition_3, ")");
412
+ break;
413
+ case 'Not In':
414
+ _right_condition = "NOT IN (".concat(_condition_3, ")");
415
+ break;
416
+ case '正则匹配':
417
+ if (db === procEnum.mysql) {
418
+ _right_condition = "CAST(".concat(_left_condition, " AS CHAR) REGEXP '").concat(_condition_3, "'");
419
+ }
420
+ if (db === procEnum.oracle) {
421
+ _right_condition = "REGEXP_LIKE(TO_CHAR(".concat(_left_condition, "), '").concat(_condition_3, "')");
422
+ }
423
+ if (db === procEnum.sqlserver) {
424
+ _right_condition = "PATINDEX('".concat(_condition_3, "', CONVERT(VARCHAR, ").concat(_left_condition, ")) = 1");
425
+ }
426
+ _left_condition = '';
427
+ break;
428
+ }
429
+ }
430
+ if (group === SQL_GROUP_TYPE.DATE) {
431
+ function transformDate(dataStr) {
432
+ return dataStr.replace(/-/g, '').replace(/:/g, '').replace(' ', '') + '00';
433
+ }
434
+ var _condition_4 = (_rightSqlItems === null || _rightSqlItems === void 0 ? void 0 : _rightSqlItems[0]) || '';
435
+ var _condition_5 = (_rightSqlItems === null || _rightSqlItems === void 0 ? void 0 : _rightSqlItems[1]) || '';
436
+ if (/^[\d- :]+$/.test(_condition_4)) {
437
+ // 日期
438
+ _condition_4 = "'".concat(transformDate(_condition_4), "'");
439
+ }
440
+ if (/^[\d- :]+$/.test(_condition_5)) {
441
+ // 日期
442
+ _condition_5 = "'".concat(transformDate(_condition_5), "'");
443
+ }
444
+ switch (condition) {
445
+ // date
446
+ case '等于':
447
+ _right_condition = "= ".concat(_condition_4);
448
+ break;
449
+ case '早于':
450
+ _right_condition = "< ".concat(_condition_4);
451
+ break;
452
+ case '晚于':
453
+ _right_condition = ">= ".concat(_condition_4);
454
+ break;
455
+ case '介于之间':
456
+ _right_condition = "(".concat(_left_condition, " >= ").concat(_condition_4, " AND ").concat(_left_condition, " < ").concat(_condition_5, ")");
457
+ _left_condition = '';
458
+ break;
459
+ case '是空的':
460
+ _right_condition = "IS NULL";
461
+ break;
462
+ case '不是空的':
463
+ _right_condition = "IS NOT NULL";
464
+ break;
465
+ }
466
+ }
467
+ sql += " ".concat(_left_condition, " ").concat(_right_condition);
468
+ }
469
+ if ([BlockTypeEnum.notExists, BlockTypeEnum.exists].includes(type)) {
470
+ var notExists = item.notExists;
471
+ if (notExists && notExists !== null && notExists !== void 0 && notExists.length) {
472
+ var _mainTable$table, _mainTable$table2;
473
+ var mainTable = notExists.find(function (v) {
474
+ return v.type === MetabaseTypeEnum.data;
475
+ });
476
+ var filterMeta = notExists.find(function (v) {
477
+ return v.type === MetabaseTypeEnum.filter;
478
+ });
479
+ var where = '';
480
+ if (filterMeta && filterMeta.filter && Array.isArray(filterMeta.filter) && filterMeta.filter.length) {
481
+ var _handleBaseType2Sql6 = _handleBaseType2Sql9(filterMeta.filter, db),
482
+ notExistsSql = _handleBaseType2Sql6.sql,
483
+ constInNotExistsFilter = _handleBaseType2Sql6.constants;
484
+ constants.push.apply(constants, (0, _toConsumableArray2["default"])(constInNotExistsFilter));
485
+ where = "WHERE ".concat(notExistsSql);
486
+ }
487
+ if (type === BlockTypeEnum.notExists) {
488
+ sql += ' NOT EXISTS';
489
+ } else {
490
+ sql += ' EXISTS';
491
+ }
492
+ sql += " (SELECT 1 FROM ".concat(mainTable === null || mainTable === void 0 || (_mainTable$table = mainTable.table) === null || _mainTable$table === void 0 ? void 0 : _mainTable$table.name, " AS ").concat(mainTable === null || mainTable === void 0 || (_mainTable$table2 = mainTable.table) === null || _mainTable$table2 === void 0 ? void 0 : _mainTable$table2.alias, " ").concat(where, ")");
493
+ }
494
+ }
495
+ if (type === BlockTypeEnum.FORMULA) {
496
+ var _handleBaseType2Sql7 = _handleBaseType2Sql9(item.args, db),
497
+ argSql = _handleBaseType2Sql7.sql,
498
+ formulaConstants = _handleBaseType2Sql7.constants;
499
+ sql += " ".concat(item.name, "(").concat(argSql, ")");
500
+ constants.push.apply(constants, (0, _toConsumableArray2["default"])(formulaConstants));
501
+ }
502
+ if (type === BlockTypeEnum.collection) {
503
+ var _handleBaseType2Sql8 = _handleBaseType2Sql9(item.list, db),
504
+ collectionSql = _handleBaseType2Sql8.sql,
505
+ collectionConstants = _handleBaseType2Sql8.constants;
506
+ sql += " ".concat(collectionSql);
507
+ constants.push.apply(constants, (0, _toConsumableArray2["default"])(collectionConstants));
508
+ }
509
+ });
510
+ return {
511
+ sql: sql,
512
+ sql_items: sql_items,
513
+ constants: constants
514
+ };
515
+ };
516
+ var _handleJoinData = function _handleJoinData(joinData) {
517
+ var db = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : procEnum.mysql;
518
+ var constants = [];
519
+ var joinList = joinData.filter(function (v) {
520
+ return v.table2.name;
521
+ }).map(function (v) {
522
+ var expressions = v.expressions,
523
+ isSubquery = v.isSubquery,
524
+ subquery = v.subquery;
525
+ var subQuery = null;
526
+ if (isSubquery) {
527
+ subQuery = subquery;
528
+ }
529
+ var _handleBaseType2Sql0 = _handleBaseType2Sql9(expressions, db),
530
+ sql = _handleBaseType2Sql0.sql,
531
+ joinConstants = _handleBaseType2Sql0.constants;
532
+ var joinCondition = "on ".concat(sql);
533
+ constants = joinConstants;
534
+ return {
535
+ alias: v.table2.alias,
536
+ tableName: v.table2.name,
537
+ tableName_zh: v.table2.name_zh,
538
+ datasourceId: v.table2.datasourceId || '',
539
+ datasourceName: v.table2.datasourceName || '',
540
+ joinCondition: joinCondition,
541
+ joinType: v.joinType,
542
+ subQuery: subQuery,
543
+ queryColumns: v.columns.filter(function (o) {
544
+ return o.select;
545
+ }).map(function (o) {
546
+ var tableAlias = v.table2.alias;
547
+ var fieldAlias = o.fieldAlias || o.name;
548
+ return {
549
+ field_sql: "".concat(tableAlias ? "".concat(tableAlias, ".").concat(o.name) : o.name, " as ").concat(fieldAlias),
550
+ read_name: o.name,
551
+ // 原字段名
552
+ name: fieldAlias,
553
+ name_zh: o.name_zh,
554
+ id: o.id
555
+ };
556
+ })
557
+ };
558
+ });
559
+ return {
560
+ joinList: joinList,
561
+ constants: constants
562
+ };
563
+ };
564
+ // 处理数据格式 - (这里才是真正处理成后端需要的格式 前面两步都是准备工作)
565
+ var _handleNesting = function handleNesting(data) {
566
+ var db = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : procEnum.mysql;
567
+ var hasInnerSql = Boolean(data.children);
568
+ var obj = {
569
+ hasInnerSql: hasInnerSql,
570
+ innerSqlStruct: hasInnerSql ? _handleNesting(data.children) : null
571
+ };
572
+ var tableData = data[MetabaseTypeEnum.data];
573
+ var joinData = data[MetabaseTypeEnum.joinData] || [];
574
+ var customColumn = data[MetabaseTypeEnum.customColumn];
575
+ var filterData = data[MetabaseTypeEnum.filter];
576
+ var summarize = data[MetabaseTypeEnum.summarize];
577
+ var sortData = data[MetabaseTypeEnum.sort];
578
+ var rowLimit = data[MetabaseTypeEnum.rowLimit];
579
+ if (tableData) {
580
+ obj.alias = tableData.table.alias;
581
+ obj.tableName = tableData.table.name;
582
+ obj.tableId = tableData.table.id;
583
+ obj.datasourceId = tableData.table.datasourceId;
584
+ obj.datasourceName = tableData.table.datasourceName;
585
+ if (tableData.isSubquery && Array.isArray(tableData.subquery)) {
586
+ // 主表是子查询
587
+ obj.tableSubQuery = tableData.subquery;
588
+ }
589
+ if (!summarize || !summarize.group.length && !summarize.by.length) {
590
+ obj.queryColumns = tableData.columns.filter(function (v) {
591
+ return v.select;
592
+ }).map(function (v) {
593
+ var _tableData$table;
594
+ var tableAlias = tableData === null || tableData === void 0 || (_tableData$table = tableData.table) === null || _tableData$table === void 0 ? void 0 : _tableData$table.alias;
595
+ var fieldAlias = v.fieldAlias || v.name;
596
+ return {
597
+ field_sql: "".concat(tableAlias ? "".concat(tableAlias, ".").concat(v.name) : v.name, " as ").concat(fieldAlias),
598
+ // 生成 sql 放 select 后面的
599
+ read_name: v.name,
600
+ // 原字段名
601
+ name: fieldAlias,
602
+ // 输出字段名
603
+ name_zh: v.name_zh,
604
+ // 字段中文名
605
+ id: v.id // 字段原 DATA_ID
606
+ };
607
+ });
608
+ }
609
+ } else {
610
+ if (!summarize || !summarize.group.length && !summarize.by.length) {
611
+ obj.alias = SummarizeAlias;
612
+ }
613
+ }
614
+ if (joinData.length) {
615
+ obj.joinTables = _handleJoinData(joinData, db).joinList;
616
+ }
617
+ if (customColumn && customColumn.customColumn.length) {
618
+ var customColumnsConstants = [];
619
+ var handleCustomColumn = function handleCustomColumn(data) {
620
+ return data.map(function (it) {
621
+ var _handleBaseType2Sql1 = _handleBaseType2Sql9(it.formulaList, db),
622
+ field_sql = _handleBaseType2Sql1.sql,
623
+ constants = _handleBaseType2Sql1.constants;
624
+ customColumnsConstants.push.apply(customColumnsConstants, (0, _toConsumableArray2["default"])(constants));
625
+ return {
626
+ field_sql: "".concat(field_sql, " as ").concat(it.name),
627
+ read_name: it.name,
628
+ name: it.name,
629
+ name_zh: it.name,
630
+ id: ''
631
+ };
632
+ });
633
+ };
634
+ obj.customColumns = handleCustomColumn(customColumn.customColumn);
635
+ obj.customColumnsConstants = customColumnsConstants;
636
+ }
637
+ if (filterData && filterData.filter.length) {
638
+ var _handleBaseType2Sql10 = _handleBaseType2Sql9(filterData.filter, db),
639
+ sql = _handleBaseType2Sql10.sql,
640
+ constants = _handleBaseType2Sql10.constants;
641
+ obj.filters = 'WHERE ' + sql;
642
+ obj.filtersConstants = constants;
643
+ }
644
+ if (summarize && (summarize.group.length || summarize.by.length)) {
645
+ obj.groupBy = {
646
+ calcColumns: [],
647
+ groupColumns: []
648
+ };
649
+ var queryColumns = [];
650
+ if (summarize.group.length) {
651
+ obj.groupBy.calcColumns = summarize.group.map(function (v) {
652
+ queryColumns.push({
653
+ field_sql: "".concat(v.sql, " as ").concat(v.fieldAlias),
654
+ read_name: '',
655
+ // 原字段名
656
+ name: v.fieldAlias,
657
+ name_zh: v.fieldAlias,
658
+ // v.quotes,
659
+ id: ''
660
+ });
661
+ return v.sql;
662
+ });
663
+ }
664
+ if (summarize.by.length) {
665
+ obj.groupBy.groupColumns = summarize.by.map(function (v) {
666
+ queryColumns.push({
667
+ field_sql: "".concat(v.sql, " as ").concat(v.fieldAlias),
668
+ read_name: '',
669
+ // 原字段名
670
+ name: v.fieldAlias,
671
+ name_zh: v.fieldAlias,
672
+ // v.name_zh,
673
+ id: v.id
674
+ });
675
+ return "".concat(v.alias, ".").concat(v.realName || v.name);
676
+ });
677
+ }
678
+ obj.queryColumns = queryColumns;
679
+ if (!tableData) {
680
+ obj.alias = summarize.alias;
681
+ }
682
+ }
683
+ if (sortData && sortData.sort.length) {
684
+ obj.orderInfos = "ORDER BY ".concat(sortData.sort.map(function (v) {
685
+ var _handleBaseType2Sql11 = _handleBaseType2Sql9(v.expression, db),
686
+ sql = _handleBaseType2Sql11.sql;
687
+ return "".concat(sql, " ").concat(v.sort);
688
+ }).join(', '));
689
+ }
690
+ if (rowLimit) {
691
+ obj.limit = Number(rowLimit.limit);
692
+ }
693
+ return obj;
694
+ };
695
+ // 反转顺序 - (将原本嵌套的顺序完全反转 最内层变成最外层)别问为什么 问就是接口需要
696
+ var reverseData = function reverseData(data) {
697
+ var arr = [];
698
+ _flatArr2(data, arr);
699
+ return _recursionArr2(arr.reverse());
700
+ };
701
+ // 分层 - (将原本平铺的格式转成 嵌套的格式)
702
+ var _layeredData = function layeredData(list) {
703
+ var res = {};
704
+ for (var i = 0; i < list.length; i++) {
705
+ var meta = list[i];
706
+ // @ts-ignore
707
+ if (meta.type === MetabaseTypeEnum.joinData) {
708
+ if (res[meta.type]) {
709
+ res[meta.type].push(meta);
710
+ } else {
711
+ res[meta.type] = [meta];
712
+ }
713
+ } else {
714
+ // @ts-ignore
715
+ res[meta.type] = meta;
716
+ }
717
+ if (meta.type === MetabaseTypeEnum.summarize) {
718
+ var nextMeta = list[i + 1];
719
+ var nextNextMeta = list[i + 2];
720
+ var nextNextNextMeta = list[i + 3];
721
+ // 将sort 和 rowLimit 归到上一层 (虽然他们两在 summarize 后面)
722
+ // 处理完 sort 和 rowLimit 之后 如果数组后面还有元素则进入下一层循环
723
+ if (nextMeta) {
724
+ if (nextMeta.type === MetabaseTypeEnum.rowLimit) {
725
+ res[nextMeta.type] = nextMeta;
726
+ if (nextNextMeta) {
727
+ res.children = _layeredData(list.slice(i + 2));
728
+ }
729
+ } else if (nextMeta.type === MetabaseTypeEnum.sort) {
730
+ res[nextMeta.type] = nextMeta;
731
+ if (nextNextMeta) {
732
+ if (nextNextMeta.type === MetabaseTypeEnum.rowLimit) {
733
+ res[nextNextMeta.type] = nextNextMeta;
734
+ if (nextNextNextMeta) {
735
+ res.children = _layeredData(list.slice(i + 3));
736
+ }
737
+ } else {
738
+ res.children = _layeredData(list.slice(i + 2));
739
+ }
740
+ }
741
+ } else {
742
+ res.children = _layeredData(list.slice(i + 1));
743
+ }
744
+ }
745
+ break;
746
+ }
747
+ }
748
+ return res;
749
+ };
750
+ var handleSqlStruct = function handleSqlStruct(list) {
751
+ var db = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : procEnum.mysql;
752
+ return _handleNesting(reverseData(_layeredData(list)), db);
753
+ };
754
+ // 处理 union
755
+ var handleSqlUnion = function handleSqlUnion(metas) {
756
+ var db = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : procEnum.mysql;
757
+ var unionMetas = metas.filter(function (it) {
758
+ return it.type === MetabaseTypeEnum.union;
759
+ });
760
+ var baseMetas = metas.filter(function (it) {
761
+ return it.type !== MetabaseTypeEnum.union;
762
+ });
763
+ var data = handleSqlStruct(baseMetas, db);
764
+ var _sqlStruct2text = _sqlStruct2text3(data, 0, db),
765
+ sql = _sqlStruct2text.sql,
766
+ fields = _sqlStruct2text.fields;
767
+ var union_fields = [fields];
768
+ if (unionMetas.length) {
769
+ // 用到了 union
770
+ unionMetas.forEach(function (it) {
771
+ if (Array.isArray(it.subquery) && it.subquery.length) {
772
+ var u_data = handleSqlStruct(it.subquery, db);
773
+ var _sqlStruct2text2 = _sqlStruct2text3(u_data, 0, db),
774
+ u_sqltext = _sqlStruct2text2.sql,
775
+ u_fields = _sqlStruct2text2.fields;
776
+ union_fields.push(u_fields);
777
+ sql += "".concat(it.union, " ").concat(u_sqltext);
778
+ }
779
+ });
780
+ }
781
+ return {
782
+ sql: sql,
783
+ fields: fields,
784
+ union_fields: union_fields
785
+ };
786
+ };
787
+ /**
788
+ * 拼 sql
789
+ * @param {meta[]} data
790
+ * @param {boolean} indent 0 是第一次进来 非 0 是第N次进来
791
+ */
792
+ var _sqlStruct2text3 = function sqlStruct2text(data) {
793
+ var indent = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 0;
794
+ var db = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : procEnum.mysql;
795
+ var sql = '';
796
+ var hasInnerSql = data.hasInnerSql,
797
+ innerSqlStruct = data.innerSqlStruct,
798
+ alias = data.alias,
799
+ tableName = data.tableName,
800
+ tableSubQuery = data.tableSubQuery,
801
+ queryColumns = data.queryColumns,
802
+ joinTables = data.joinTables,
803
+ filters = data.filters,
804
+ orderInfos = data.orderInfos,
805
+ limit = data.limit,
806
+ customColumns = data.customColumns,
807
+ groupBy = data.groupBy;
808
+ sql += "SELECT ";
809
+ var firstEntry = !indent;
810
+ // -------- 处理 fields --------
811
+ // 情况一、一层 带聚合 字段是 聚合字段
812
+ // 情况二、一层 不带聚合 字段是 主表和关联表的字段
813
+ // 情况三、二层 带聚合 第一层 聚合字段 + 关联表字段 第二层 聚合字段 第三层 聚合字段
814
+ var flag = false; // 是否加逗号
815
+ if (limit && db === procEnum.sqlserver) {
816
+ sql += "TOP(".concat(limit, ") ");
817
+ }
818
+ if (hasInnerSql) {
819
+ // 情况三 innerSqlStruct.queryColumns 是内层 聚合输出的字段,这种字段虽说是内层的,但是其实外层也需要
820
+ if (innerSqlStruct.queryColumns && innerSqlStruct.queryColumns.length) {
821
+ sql += innerSqlStruct.queryColumns.map(function (v) {
822
+ return "".concat(alias, ".").concat(v.name, " as ").concat(v.name);
823
+ }).join(', ') + ' ';
824
+ flag = true;
825
+ }
826
+ } else {
827
+ if (Array.isArray(queryColumns) && queryColumns.length) {
828
+ // 情况一 queryColumns 是聚合字段
829
+ // 情况二 queryColumns 是主表字段
830
+ // 情况三 queryColumns 是聚合字段
831
+ flag = true;
832
+ sql += queryColumns.map(function (v) {
833
+ return v.field_sql;
834
+ }).join(', ') + ' ';
835
+ }
836
+ }
837
+ if (firstEntry && joinTables && !groupBy) {
838
+ // 情况二 joinTables 是关联表字段
839
+ // 情况三 joinTables 是关联表字段
840
+ joinTables.forEach(function (it) {
841
+ if (Array.isArray(it.queryColumns) && it.queryColumns.length) {
842
+ if (flag) {
843
+ sql += ', ';
844
+ }
845
+ sql += it.queryColumns.map(function (v) {
846
+ return v.field_sql;
847
+ }).join(', ') + ' ';
848
+ flag = true;
849
+ }
850
+ });
851
+ }
852
+ if (customColumns && customColumns.length) {
853
+ if (flag) {
854
+ sql += ', ';
855
+ }
856
+ sql += customColumns.map(function (v) {
857
+ return v.field_sql;
858
+ }).join(', ') + ' ';
859
+ }
860
+ // -------- 处理 main table --------
861
+ sql += 'FROM ';
862
+ var as = db === procEnum.oracle ? '' : 'AS ';
863
+ if (hasInnerSql) {
864
+ sql += "(".concat(_sqlStruct2text3(innerSqlStruct, indent + 1, db).sql, ") ").concat(as).concat(alias, " ");
865
+ } else {
866
+ if (tableSubQuery) {
867
+ // 子查询
868
+ sql += "(".concat(handleSqlUnion(tableSubQuery, db).sql, ") ").concat(as).concat(alias, " ");
869
+ } else {
870
+ sql += "".concat(tableName, " ").concat(as).concat(alias, " ");
871
+ }
872
+ }
873
+ // -------- 处理 left join --------
874
+ if (joinTables) {
875
+ joinTables.forEach(function (it) {
876
+ if (it.subQuery) {
877
+ // 子查询
878
+ sql += "".concat(it.joinType, " (").concat(handleSqlUnion(it.subQuery, db).sql, ") ").concat(as).concat(it.alias, " ").concat(it.joinCondition, " ");
879
+ } else {
880
+ sql += "".concat(it.joinType, " ").concat(it.tableName, " ").concat(as).concat(it.alias, " ").concat(it.joinCondition, " ");
881
+ }
882
+ });
883
+ }
884
+ // -------- 处理 where --------
885
+ if (filters) {
886
+ sql += "".concat(filters, " ");
887
+ if (limit && db === procEnum.oracle) {
888
+ if (filters) {
889
+ sql += "AND ROWNUM <= ".concat(limit, " ");
890
+ } else {
891
+ sql += "WHERE ROWNUM <= ".concat(limit, " ");
892
+ }
893
+ }
894
+ }
895
+ // -------- 处理 group by --------
896
+ if (Array.isArray(groupBy === null || groupBy === void 0 ? void 0 : groupBy.groupColumns) && groupBy.groupColumns.length) {
897
+ sql += "GROUP BY ".concat(groupBy.groupColumns.map(function (it) {
898
+ return it;
899
+ }).join(', '), " ");
900
+ }
901
+ // -------- 处理 orderby --------
902
+ if (orderInfos) {
903
+ sql += "".concat(orderInfos, " ");
904
+ }
905
+ // -------- 处理 limit --------
906
+ if (limit && db === procEnum.mysql) {
907
+ sql += "LIMIT ".concat(limit, " ");
908
+ }
909
+ // -------- 获取 字段列表 --------
910
+ var fields = [];
911
+ if (firstEntry) {
912
+ function addFields(data) {
913
+ var name = data.name,
914
+ name_zh = data.name_zh,
915
+ _data$id = data.id,
916
+ id = _data$id === void 0 ? '' : _data$id;
917
+ fields.push({
918
+ FIELD_ID: name,
919
+ FIELD_NAME: name_zh,
920
+ id: id
921
+ });
922
+ }
923
+ if (hasInnerSql) {
924
+ if (innerSqlStruct.queryColumns && innerSqlStruct.queryColumns.length) {
925
+ innerSqlStruct.queryColumns.map(function (v) {
926
+ return addFields(v);
927
+ });
928
+ }
929
+ } else {
930
+ if (Array.isArray(queryColumns) && queryColumns.length) {
931
+ queryColumns.map(function (v) {
932
+ return addFields(v);
933
+ });
934
+ }
935
+ }
936
+ if (joinTables && !groupBy) {
937
+ joinTables.forEach(function (it) {
938
+ if (Array.isArray(it.queryColumns) && it.queryColumns.length) {
939
+ it.queryColumns.map(function (v) {
940
+ return addFields(v);
941
+ });
942
+ }
943
+ });
944
+ }
945
+ if (customColumns && customColumns.length) {
946
+ customColumns.map(function (v) {
947
+ return addFields(v);
948
+ });
949
+ }
950
+ }
951
+ return {
952
+ sql: sql,
953
+ fields: fields
954
+ };
955
+ };
956
+ var transformSql = exports.transformSql = function transformSql(metas) {
957
+ var db = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : procEnum.mysql;
958
+ // let new_metas = upgradeLegacyData(metas);
959
+ var _handleSqlUnion = handleSqlUnion(metas, db),
960
+ sql = _handleSqlUnion.sql,
961
+ fields = _handleSqlUnion.fields,
962
+ union_fields = _handleSqlUnion.union_fields;
963
+ return {
964
+ sql: sql,
965
+ fields: fields,
966
+ union_fields: union_fields
967
+ };
968
+ };